Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp
Warning:line 419, column 9
Value stored to 'nextState' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_netwerk_base2.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/base -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/xpcom/components -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/webtransport -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/socket -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/security/manager/ssl -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/components -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-16-034744-15991-1 -x c++ Unified_cpp_netwerk_base2.cpp
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim:set ts=4 sts=2 sw=2 et cin: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsIOService.h"
8#include "nsInputStreamPump.h"
9#include "nsIStreamTransportService.h"
10#include "nsIThreadRetargetableStreamListener.h"
11#include "nsThreadUtils.h"
12#include "nsCOMPtr.h"
13#include "mozilla/Logging.h"
14#include "mozilla/NonBlockingAsyncInputStream.h"
15#include "mozilla/ProfilerLabels.h"
16#include "mozilla/SlicedInputStream.h"
17#include "mozilla/StaticPrefs_network.h"
18#include "nsIStreamListener.h"
19#include "nsILoadGroup.h"
20#include "nsNetCID.h"
21#include "nsNetUtil.h"
22#include "nsStreamUtils.h"
23#include <algorithm>
24
25//
26// MOZ_LOG=nsStreamPump:5
27//
28static mozilla::LazyLogModule gStreamPumpLog("nsStreamPump");
29#undef LOG
30#define LOG(args) MOZ_LOG(gStreamPumpLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = gStreamPumpLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
31
32//-----------------------------------------------------------------------------
33// nsInputStreamPump methods
34//-----------------------------------------------------------------------------
35
36nsInputStreamPump::nsInputStreamPump() : mOffMainThread(!NS_IsMainThread()) {}
37
38nsresult nsInputStreamPump::Create(nsInputStreamPump** result,
39 nsIInputStream* stream, uint32_t segsize,
40 uint32_t segcount, bool closeWhenDone,
41 nsISerialEventTarget* mainThreadTarget) {
42 nsresult rv = NS_ERROR_OUT_OF_MEMORY;
43 RefPtr<nsInputStreamPump> pump = new nsInputStreamPump();
44 if (pump) {
45 rv = pump->Init(stream, segsize, segcount, closeWhenDone, mainThreadTarget);
46 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
47 pump.forget(result);
48 }
49 }
50 return rv;
51}
52
53struct PeekData {
54 PeekData(nsInputStreamPump::PeekSegmentFun fun, void* closure)
55 : mFunc(fun), mClosure(closure) {}
56
57 nsInputStreamPump::PeekSegmentFun mFunc;
58 void* mClosure;
59};
60
61static nsresult CallPeekFunc(nsIInputStream* aInStream, void* aClosure,
62 const char* aFromSegment, uint32_t aToOffset,
63 uint32_t aCount, uint32_t* aWriteCount) {
64 NS_ASSERTION(aToOffset == 0, "Called more than once?")do { if (!(aToOffset == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Called more than once?", "aToOffset == 0", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 64); MOZ_PretendNoReturn(); } } while (0)
;
65 NS_ASSERTION(aCount > 0, "Called without data?")do { if (!(aCount > 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Called without data?", "aCount > 0", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 65); MOZ_PretendNoReturn(); } } while (0)
;
66
67 PeekData* data = static_cast<PeekData*>(aClosure);
68 data->mFunc(data->mClosure, reinterpret_cast<const uint8_t*>(aFromSegment),
69 aCount);
70 return NS_BINDING_ABORTED;
71}
72
73nsresult nsInputStreamPump::PeekStream(PeekSegmentFun callback, void* closure) {
74 RecursiveMutexAutoLock lock(mMutex);
75
76 MOZ_ASSERT(mAsyncStream, "PeekStream called without stream")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncStream))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAsyncStream" " ("
"PeekStream called without stream" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 76); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncStream"
") (" "PeekStream called without stream" ")"); do { *((volatile
int*)__null) = 76; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
77
78 nsresult rv = CreateBufferedStreamIfNeeded();
79 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 79); return rv; } } while (false)
;
80
81 // See if the pipe is closed by checking the return of Available.
82 uint64_t dummy64;
83 rv = mAsyncStream->Available(&dummy64);
84 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
85 uint32_t dummy = (uint32_t)std::min(dummy64, (uint64_t)UINT32_MAX(4294967295U));
86
87 PeekData data(callback, closure);
88 return mAsyncStream->ReadSegments(
89 CallPeekFunc, &data, mozilla::net::nsIOService::gDefaultSegmentSize,
90 &dummy);
91}
92
93nsresult nsInputStreamPump::EnsureWaiting() {
94 mMutex.AssertCurrentThreadIn();
95
96 // no need to worry about multiple threads... an input stream pump lives
97 // on only one thread at a time.
98 MOZ_ASSERT(mAsyncStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncStream))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAsyncStream", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 98); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncStream"
")"); do { *((volatile int*)__null) = 98; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
99 if (!mWaitingForInputStreamReady && !mProcessingCallbacks) {
100 // Ensure OnStateStop is called on the main thread only when this pump is
101 // created on main thread.
102 if (mState == STATE_STOP && !mOffMainThread) {
103 nsCOMPtr<nsISerialEventTarget> mainThread =
104 mLabeledMainThreadTarget
105 ? mLabeledMainThreadTarget
106 : do_AddRef(mozilla::GetMainThreadSerialEventTarget());
107 if (mTargetThread != mainThread) {
108 mTargetThread = mainThread;
109 }
110 }
111 MOZ_ASSERT(mTargetThread)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTargetThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mTargetThread))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mTargetThread",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTargetThread"
")"); do { *((volatile int*)__null) = 111; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
112 nsresult rv = mAsyncStream->AsyncWait(this, 0, 0, mTargetThread);
113 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
114 NS_ERROR("AsyncWait failed")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "AsyncWait failed", "Error"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 114); MOZ_PretendNoReturn(); } while (0)
;
115 return rv;
116 }
117 // Any retargeting during STATE_START or START_TRANSFER is complete
118 // after the call to AsyncWait; next callback will be on mTargetThread.
119 mRetargeting = false;
120 mWaitingForInputStreamReady = true;
121 }
122 return NS_OK;
123}
124
125//-----------------------------------------------------------------------------
126// nsInputStreamPump::nsISupports
127//-----------------------------------------------------------------------------
128
129// although this class can only be accessed from one thread at a time, we do
130// allow its ownership to move from thread to thread, assuming the consumer
131// understands the limitations of this.
132NS_IMPL_ADDREF(nsInputStreamPump)MozExternalRefCountType nsInputStreamPump::AddRef(void) { static_assert
(!std::is_destructible_v<nsInputStreamPump>, "Reference-counted class "
"nsInputStreamPump" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
132; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsInputStreamPump" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsInputStreamPump" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsInputStreamPump\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsInputStreamPump\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 132; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsInputStreamPump" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsInputStreamPump"
), (uint32_t)(sizeof(*this))); return count; }
133NS_IMPL_RELEASE(nsInputStreamPump)MozExternalRefCountType nsInputStreamPump::Release(void) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 133
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsInputStreamPump" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsInputStreamPump" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsInputStreamPump\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsInputStreamPump\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 133; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsInputStreamPump" " not thread-safe"); const
char* const nametmp = "nsInputStreamPump"; nsrefcnt count = --
mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; }
134NS_INTERFACE_MAP_BEGIN(nsInputStreamPump)nsresult nsInputStreamPump::QueryInterface(const nsIID& aIID
, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 134); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
135 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
136 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableRequest>)) foundInterface
= static_cast<nsIThreadRetargetableRequest*>(this); else
137 NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInputStreamCallback>)) foundInterface
= static_cast<nsIInputStreamCallback*>(this); else
138 NS_INTERFACE_MAP_ENTRY(nsIInputStreamPump)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInputStreamPump>)) foundInterface
= static_cast<nsIInputStreamPump*>(this); else
139 NS_INTERFACE_MAP_ENTRY_CONCRETE(nsInputStreamPump)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsInputStreamPump>)) { *aInstancePtr
= do_AddRef(static_cast<nsInputStreamPump*>(this)).take
(); return NS_OK; } else
140 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStreamPump)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIInputStreamPump*>(this
)); else
141NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 141; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
142
143//-----------------------------------------------------------------------------
144// nsInputStreamPump::nsIRequest
145//-----------------------------------------------------------------------------
146
147NS_IMETHODIMPnsresult
148nsInputStreamPump::GetName(nsACString& result) {
149 RecursiveMutexAutoLock lock(mMutex);
150
151 result.Truncate();
152 return NS_OK;
153}
154
155NS_IMETHODIMPnsresult
156nsInputStreamPump::IsPending(bool* result) {
157 RecursiveMutexAutoLock lock(mMutex);
158
159 *result = (mState != STATE_IDLE && mState != STATE_DEAD);
160 return NS_OK;
161}
162
163NS_IMETHODIMPnsresult
164nsInputStreamPump::GetStatus(nsresult* status) {
165 RecursiveMutexAutoLock lock(mMutex);
166
167 *status = mStatus;
168 return NS_OK;
169}
170
171NS_IMETHODIMPnsresult nsInputStreamPump::SetCanceledReason(const nsACString& aReason) {
172 return SetCanceledReasonImpl(aReason);
173}
174
175NS_IMETHODIMPnsresult nsInputStreamPump::GetCanceledReason(nsACString& aReason) {
176 return GetCanceledReasonImpl(aReason);
177}
178
179NS_IMETHODIMPnsresult nsInputStreamPump::CancelWithReason(nsresult aStatus,
180 const nsACString& aReason) {
181 return CancelWithReasonImpl(aStatus, aReason);
182}
183
184NS_IMETHODIMPnsresult
185nsInputStreamPump::Cancel(nsresult status) {
186 RecursiveMutexAutoLock lock(mMutex);
187
188 AssertOnThread();
189
190 LOG(("nsInputStreamPump::Cancel [this=%p status=%" PRIx32"x" "]\n", this,
191 static_cast<uint32_t>(status)));
192
193 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
194 LOG((" already canceled\n"));
195 return NS_OK;
196 }
197
198 NS_ASSERTION(NS_FAILED(status), "cancel with non-failure status code")do { if (!(((bool)(__builtin_expect(!!(NS_FAILED_impl(status)
), 0))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "cancel with non-failure status code"
, "NS_FAILED(status)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 198); MOZ_PretendNoReturn(); } } while (0)
;
199 mStatus = status;
200
201 // close input stream
202 if (mAsyncStream) {
203 // If mSuspendCount != 0, EnsureWaiting will be called by Resume().
204 // Note that while suspended, OnInputStreamReady will
205 // not do anything, and also note that calling asyncWait
206 // on a closed stream works and will dispatch an event immediately.
207
208 nsCOMPtr<nsIEventTarget> currentTarget = NS_GetCurrentThread();
209 if (mTargetThread && currentTarget != mTargetThread) {
210 nsresult rv = mTargetThread->Dispatch(NS_NewRunnableFunction(
211 "nsInputStreamPump::Cancel", [self = RefPtr{this}, status] {
212 RecursiveMutexAutoLock lock(self->mMutex);
213 if (!self->mAsyncStream) {
214 return;
215 }
216 self->mAsyncStream->CloseWithStatus(status);
217 if (self->mSuspendCount == 0) {
218 self->EnsureWaiting();
219 }
220 }));
221 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 221); return rv; } } while (false)
;
222 } else {
223 mAsyncStream->CloseWithStatus(status);
224 if (mSuspendCount == 0) {
225 EnsureWaiting();
226 }
227 }
228 }
229 return NS_OK;
230}
231
232NS_IMETHODIMPnsresult
233nsInputStreamPump::Suspend() {
234 RecursiveMutexAutoLock lock(mMutex);
235
236 LOG(("nsInputStreamPump::Suspend [this=%p]\n", this));
237 NS_ENSURE_TRUE(mState != STATE_IDLE && mState != STATE_DEAD,do { if ((__builtin_expect(!!(!(mState != STATE_IDLE &&
mState != STATE_DEAD)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "mState != STATE_IDLE && mState != STATE_DEAD"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 238); return NS_ERROR_UNEXPECTED; } } while (false)
238 NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mState != STATE_IDLE &&
mState != STATE_DEAD)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "mState != STATE_IDLE && mState != STATE_DEAD"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 238); return NS_ERROR_UNEXPECTED; } } while (false)
;
239 ++mSuspendCount;
240 return NS_OK;
241}
242
243NS_IMETHODIMPnsresult
244nsInputStreamPump::Resume() {
245 RecursiveMutexAutoLock lock(mMutex);
246
247 LOG(("nsInputStreamPump::Resume [this=%p]\n", this));
248 NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mSuspendCount > 0)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mSuspendCount > 0"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 248); return NS_ERROR_UNEXPECTED; } } while (false)
;
249 NS_ENSURE_TRUE(mState != STATE_IDLE && mState != STATE_DEAD,do { if ((__builtin_expect(!!(!(mState != STATE_IDLE &&
mState != STATE_DEAD)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "mState != STATE_IDLE && mState != STATE_DEAD"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 250); return NS_ERROR_UNEXPECTED; } } while (false)
250 NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mState != STATE_IDLE &&
mState != STATE_DEAD)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "mState != STATE_IDLE && mState != STATE_DEAD"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 250); return NS_ERROR_UNEXPECTED; } } while (false)
;
251
252 // There is a brief in-between state when we null out mAsyncStream in
253 // OnStateStop() before calling OnStopRequest, and only afterwards set
254 // STATE_DEAD, which we need to handle gracefully.
255 if (--mSuspendCount == 0 && mAsyncStream) {
256 EnsureWaiting();
257 }
258 return NS_OK;
259}
260
261NS_IMETHODIMPnsresult
262nsInputStreamPump::GetLoadFlags(nsLoadFlags* aLoadFlags) {
263 RecursiveMutexAutoLock lock(mMutex);
264
265 *aLoadFlags = mLoadFlags;
266 return NS_OK;
267}
268
269NS_IMETHODIMPnsresult
270nsInputStreamPump::SetLoadFlags(nsLoadFlags aLoadFlags) {
271 RecursiveMutexAutoLock lock(mMutex);
272
273 mLoadFlags = aLoadFlags;
274 return NS_OK;
275}
276
277NS_IMETHODIMPnsresult
278nsInputStreamPump::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
279 return GetTRRModeImpl(aTRRMode);
280}
281
282NS_IMETHODIMPnsresult
283nsInputStreamPump::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
284 return SetTRRModeImpl(aTRRMode);
285}
286
287NS_IMETHODIMPnsresult
288nsInputStreamPump::GetLoadGroup(nsILoadGroup** aLoadGroup) {
289 RecursiveMutexAutoLock lock(mMutex);
290
291 *aLoadGroup = do_AddRef(mLoadGroup).take();
292 return NS_OK;
293}
294
295NS_IMETHODIMPnsresult
296nsInputStreamPump::SetLoadGroup(nsILoadGroup* aLoadGroup) {
297 RecursiveMutexAutoLock lock(mMutex);
298
299 mLoadGroup = aLoadGroup;
300 return NS_OK;
301}
302
303//-----------------------------------------------------------------------------
304// nsInputStreamPump::nsIInputStreamPump implementation
305//-----------------------------------------------------------------------------
306
307NS_IMETHODIMPnsresult
308nsInputStreamPump::Init(nsIInputStream* stream, uint32_t segsize,
309 uint32_t segcount, bool closeWhenDone,
310 nsISerialEventTarget* mainThreadTarget) {
311 // probably we can't be multithread-accessed yet
312 RecursiveMutexAutoLock lock(mMutex);
313 NS_ENSURE_TRUE(mState == STATE_IDLE, NS_ERROR_IN_PROGRESS)do { if ((__builtin_expect(!!(!(mState == STATE_IDLE)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mState == STATE_IDLE"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 313); return NS_ERROR_IN_PROGRESS; } } while (false)
;
314
315 mStream = stream;
316 mSegSize = segsize;
317 mSegCount = segcount;
318 mCloseWhenDone = closeWhenDone;
319 mLabeledMainThreadTarget = mainThreadTarget;
320 if (mOffMainThread && mLabeledMainThreadTarget) {
321 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Init stream pump off main thread with a main thread event target."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Init stream pump off main thread with a main thread event target."
")"); do { *((volatile int*)__null) = 323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
322 false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Init stream pump off main thread with a main thread event target."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Init stream pump off main thread with a main thread event target."
")"); do { *((volatile int*)__null) = 323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
323 "Init stream pump off main thread with a main thread event target.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Init stream pump off main thread with a main thread event target."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Init stream pump off main thread with a main thread event target."
")"); do { *((volatile int*)__null) = 323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
324 return NS_ERROR_FAILURE;
325 }
326
327 return NS_OK;
328}
329
330NS_IMETHODIMPnsresult
331nsInputStreamPump::AsyncRead(nsIStreamListener* listener) {
332 RecursiveMutexAutoLock lock(mMutex);
333
334 // This ensures only one thread can interact with a pump at a time
335 NS_ENSURE_TRUE(mState == STATE_IDLE, NS_ERROR_IN_PROGRESS)do { if ((__builtin_expect(!!(!(mState == STATE_IDLE)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mState == STATE_IDLE"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 335); return NS_ERROR_IN_PROGRESS; } } while (false)
;
336 NS_ENSURE_ARG_POINTER(listener)do { if ((__builtin_expect(!!(!(listener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "listener" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 336); return NS_ERROR_INVALID_POINTER; } } while (false)
;
337 MOZ_ASSERT(NS_IsMainThread() || mOffMainThread,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || mOffMainThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread() || mOffMainThread
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"NS_IsMainThread() || mOffMainThread" " (" "nsInputStreamPump should be read from the "
"main thread only." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || mOffMainThread"
") (" "nsInputStreamPump should be read from the " "main thread only."
")"); do { *((volatile int*)__null) = 339; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
338 "nsInputStreamPump should be read from the "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || mOffMainThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread() || mOffMainThread
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"NS_IsMainThread() || mOffMainThread" " (" "nsInputStreamPump should be read from the "
"main thread only." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || mOffMainThread"
") (" "nsInputStreamPump should be read from the " "main thread only."
")"); do { *((volatile int*)__null) = 339; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
339 "main thread only.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || mOffMainThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread() || mOffMainThread
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"NS_IsMainThread() || mOffMainThread" " (" "nsInputStreamPump should be read from the "
"main thread only." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || mOffMainThread"
") (" "nsInputStreamPump should be read from the " "main thread only."
")"); do { *((volatile int*)__null) = 339; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
340
341 nsresult rv = NS_MakeAsyncNonBlockingInputStream(
342 mStream.forget(), getter_AddRefs(mAsyncStream), mCloseWhenDone, mSegSize,
343 mSegCount);
344 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 344)
) {
345 return rv;
346 }
347
348 MOZ_ASSERT(mAsyncStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncStream))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAsyncStream", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 348); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncStream"
")"); do { *((volatile int*)__null) = 348; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
349
350 // mStreamOffset now holds the number of bytes currently read.
351 mStreamOffset = 0;
352
353 // grab event queue (we must do this here by contract, since all notifications
354 // must go to the thread which called AsyncRead)
355 if (NS_IsMainThread() && mLabeledMainThreadTarget) {
356 mTargetThread = mLabeledMainThreadTarget;
357 } else {
358 mTargetThread = mozilla::GetCurrentSerialEventTarget();
359 }
360 NS_ENSURE_STATE(mTargetThread)do { if ((__builtin_expect(!!(!(mTargetThread)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mTargetThread" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 360); return NS_ERROR_UNEXPECTED; } } while (false)
;
361
362 rv = EnsureWaiting();
363 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
364
365 if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
366
367 mState = STATE_START;
368 mListener = listener;
369 return NS_OK;
370}
371
372//-----------------------------------------------------------------------------
373// nsInputStreamPump::nsIInputStreamCallback implementation
374//-----------------------------------------------------------------------------
375
376NS_IMETHODIMPnsresult
377nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream* stream) {
378 LOG(("nsInputStreamPump::OnInputStreamReady [this=%p]\n", this));
379
380 AUTO_PROFILER_LABEL("nsInputStreamPump::OnInputStreamReady", NETWORK)mozilla::AutoProfilerLabel raiiObject380( "nsInputStreamPump::OnInputStreamReady"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
381
382 // this function has been called from a PLEvent, so we can safely call
383 // any listener or progress sink methods directly from here.
384
385 for (;;) {
386 // There should only be one iteration of this loop happening at a time.
387 // To prevent AsyncWait() (called during callbacks or on other threads)
388 // from creating a parallel OnInputStreamReady(), we use:
389 // -- a mutex; and
390 // -- a boolean mProcessingCallbacks to detect parallel loops
391 // when exiting the mutex for callbacks.
392 RecursiveMutexAutoLock lock(mMutex);
393
394 // Prevent parallel execution during callbacks, while out of mutex.
395 if (mProcessingCallbacks) {
396 MOZ_ASSERT(!mProcessingCallbacks)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mProcessingCallbacks)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mProcessingCallbacks))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mProcessingCallbacks"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mProcessingCallbacks"
")"); do { *((volatile int*)__null) = 396; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
397 break;
398 }
399 mProcessingCallbacks = true;
400 if (mSuspendCount || mState == STATE_IDLE || mState == STATE_DEAD) {
401 mWaitingForInputStreamReady = false;
402 mProcessingCallbacks = false;
403 break;
404 }
405
406 uint32_t nextState;
407 switch (mState) {
408 case STATE_START:
409 nextState = OnStateStart();
410 break;
411 case STATE_TRANSFER:
412 nextState = OnStateTransfer();
413 break;
414 case STATE_STOP:
415 mRetargeting = false;
416 nextState = OnStateStop();
417 break;
418 default:
419 nextState = 0;
Value stored to 'nextState' is never read
420 MOZ_ASSERT_UNREACHABLE("Unknown enum value.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown enum value." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown enum value." ")"); do { *
((volatile int*)__null) = 420; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
421 return NS_ERROR_UNEXPECTED;
422 }
423
424 bool stillTransferring =
425 (mState == STATE_TRANSFER && nextState == STATE_TRANSFER);
426 if (stillTransferring) {
427 NS_ASSERTION(NS_SUCCEEDED(mStatus),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Should not have failed status for ongoing transfer"
, "NS_SUCCEEDED(mStatus)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 428); MOZ_PretendNoReturn(); } } while (0)
428 "Should not have failed status for ongoing transfer")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Should not have failed status for ongoing transfer"
, "NS_SUCCEEDED(mStatus)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 428); MOZ_PretendNoReturn(); } } while (0)
;
429 } else {
430 NS_ASSERTION(mState != nextState,do { if (!(mState != nextState)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Only OnStateTransfer can be called more than once.", "mState != nextState"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0)
431 "Only OnStateTransfer can be called more than once.")do { if (!(mState != nextState)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Only OnStateTransfer can be called more than once.", "mState != nextState"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0)
;
432 }
433 if (mRetargeting) {
434 NS_ASSERTION(mState != STATE_STOP,do { if (!(mState != STATE_STOP)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Retargeting should not happen during OnStateStop.", "mState != STATE_STOP"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 435); MOZ_PretendNoReturn(); } } while (0)
435 "Retargeting should not happen during OnStateStop.")do { if (!(mState != STATE_STOP)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Retargeting should not happen during OnStateStop.", "mState != STATE_STOP"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 435); MOZ_PretendNoReturn(); } } while (0)
;
436 }
437
438 // Set mRetargeting so EnsureWaiting will be called. It ensures that
439 // OnStateStop is called on the main thread.
440 if (nextState == STATE_STOP && !NS_IsMainThread() && !mOffMainThread) {
441 mRetargeting = true;
442 }
443
444 // Unset mProcessingCallbacks here (while we have lock) so our own call to
445 // EnsureWaiting isn't blocked by it.
446 mProcessingCallbacks = false;
447
448 // We must break the loop if suspended during one of the previous
449 // operation.
450 if (mSuspendCount) {
451 mState = nextState;
452 mWaitingForInputStreamReady = false;
453 break;
454 }
455
456 // Wait asynchronously if there is still data to transfer, or we're
457 // switching event delivery to another thread.
458 if (stillTransferring || mRetargeting) {
459 mState = nextState;
460 mWaitingForInputStreamReady = false;
461 nsresult rv = EnsureWaiting();
462 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) break;
463
464 // Failure to start asynchronous wait: stop transfer.
465 // Do not set mStatus if it was previously set to report a failure.
466 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
467 mStatus = rv;
468 }
469 nextState = STATE_STOP;
470 }
471
472 mState = nextState;
473 }
474 return NS_OK;
475}
476
477uint32_t nsInputStreamPump::OnStateStart() {
478 mMutex.AssertCurrentThreadIn();
479
480 AUTO_PROFILER_LABEL("nsInputStreamPump::OnStateStart", NETWORK)mozilla::AutoProfilerLabel raiiObject480( "nsInputStreamPump::OnStateStart"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
481
482 LOG((" OnStateStart [this=%p]\n", this));
483
484 nsresult rv;
485
486 // need to check the reason why the stream is ready. this is required
487 // so our listener can check our status from OnStartRequest.
488 // XXX async streams should have a GetStatus method!
489 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
490 uint64_t avail;
491 rv = mAsyncStream->Available(&avail);
492 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_BASE_STREAM_CLOSED) mStatus = rv;
493 }
494
495 {
496 nsCOMPtr<nsIStreamListener> listener = mListener;
497 // We're on the writing thread
498 AssertOnThread();
499
500 // Note: Must exit mutex for call to OnStartRequest to avoid
501 // deadlocks when calls to RetargetDeliveryTo for multiple
502 // nsInputStreamPumps are needed (e.g. nsHttpChannel).
503 RecursiveMutexAutoUnlock unlock(mMutex);
504 rv = listener->OnStartRequest(this);
505 }
506
507 // an error returned from OnStartRequest should cause us to abort; however,
508 // we must not stomp on mStatus if already canceled.
509 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) mStatus = rv;
510
511 return NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) ? STATE_TRANSFER : STATE_STOP;
512}
513
514uint32_t nsInputStreamPump::OnStateTransfer() {
515 mMutex.AssertCurrentThreadIn();
516
517 AUTO_PROFILER_LABEL("nsInputStreamPump::OnStateTransfer", NETWORK)mozilla::AutoProfilerLabel raiiObject517( "nsInputStreamPump::OnStateTransfer"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
518
519 LOG((" OnStateTransfer [this=%p]\n", this));
520
521 // if canceled, go directly to STATE_STOP...
522 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) return STATE_STOP;
523
524 nsresult rv = CreateBufferedStreamIfNeeded();
525 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 525)
) {
526 return STATE_STOP;
527 }
528
529 uint64_t avail;
530 rv = mAsyncStream->Available(&avail);
531 LOG((" Available returned [stream=%p rv=%" PRIx32"x" " avail=%" PRIu64"l" "u" "]\n",
532 mAsyncStream.get(), static_cast<uint32_t>(rv), avail));
533
534 if (rv == NS_BASE_STREAM_CLOSED) {
535 rv = NS_OK;
536 avail = 0;
537 } else if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && avail) {
538 // we used to limit avail to 16K - we were afraid some ODA handlers
539 // might assume they wouldn't get more than 16K at once
540 // we're removing that limit since it speeds up local file access.
541 // Now there's an implicit 64K limit of 4 16K segments
542 // NOTE: ok, so the story is as follows. OnDataAvailable impls
543 // are by contract supposed to consume exactly |avail| bytes.
544 // however, many do not... mailnews... stream converters...
545 // cough, cough. the input stream pump is fairly tolerant
546 // in this regard; however, if an ODA does not consume any
547 // data from the stream, then we could potentially end up in
548 // an infinite loop. we do our best here to try to catch
549 // such an error. (see bug 189672)
550
551 // in most cases this QI will succeed (mAsyncStream is almost always
552 // a nsPipeInputStream, which implements nsITellableStream::Tell).
553 int64_t offsetBefore;
554 nsCOMPtr<nsITellableStream> tellable = do_QueryInterface(mAsyncStream);
555 if (tellable && NS_FAILED(tellable->Tell(&offsetBefore))((bool)(__builtin_expect(!!(NS_FAILED_impl(tellable->Tell(
&offsetBefore))), 0)))
) {
556 MOZ_ASSERT_UNREACHABLE("Tell failed on readable stream")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Tell failed on readable stream" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Tell failed on readable stream" ")"
); do { *((volatile int*)__null) = 556; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
557 offsetBefore = 0;
558 }
559
560 uint32_t odaAvail = avail > UINT32_MAX(4294967295U) ? UINT32_MAX(4294967295U) : uint32_t(avail);
561
562 LOG((" calling OnDataAvailable [offset=%" PRIu64"l" "u" " count=%" PRIu64"l" "u"
563 "(%u)]\n",
564 mStreamOffset, avail, odaAvail));
565
566 {
567 // We may be called on non-MainThread even if mOffMainThread is
568 // false, due to RetargetDeliveryTo(), so don't use AssertOnThread()
569 if (mTargetThread) {
570 MOZ_ASSERT(mTargetThread->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTargetThread->IsOnCurrentThread())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(mTargetThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mTargetThread->IsOnCurrentThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTargetThread->IsOnCurrentThread()"
")"); do { *((volatile int*)__null) = 570; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
571 } else {
572 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 572; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
573 }
574
575 nsCOMPtr<nsIStreamListener> listener = mListener;
576 // Note: Must exit mutex for call to OnStartRequest to avoid
577 // deadlocks when calls to RetargetDeliveryTo for multiple
578 // nsInputStreamPumps are needed (e.g. nsHttpChannel).
579 RecursiveMutexAutoUnlock unlock(mMutex);
580 // We're on the writing thread for mListener and mAsyncStream.
581 // mStreamOffset is only touched in OnStateTransfer, and AsyncRead
582 // shouldn't be called during OnDataAvailable()
583
584 MOZ_PUSH_IGNORE_THREAD_SAFETYGCC diagnostic push GCC diagnostic ignored "-Wthread-safety"
585 rv = listener->OnDataAvailable(this, mAsyncStream, mStreamOffset,
586 odaAvail);
587 MOZ_POP_THREAD_SAFETYGCC diagnostic pop
588 }
589
590 // don't enter this code if ODA failed or called Cancel
591 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
592 // test to see if this ODA failed to consume data
593 if (tellable) {
594 // NOTE: if Tell fails, which can happen if the stream is
595 // now closed, then we assume that everything was read.
596 int64_t offsetAfter;
597 if (NS_FAILED(tellable->Tell(&offsetAfter))((bool)(__builtin_expect(!!(NS_FAILED_impl(tellable->Tell(
&offsetAfter))), 0)))
) {
598 offsetAfter = offsetBefore + odaAvail;
599 }
600 if (offsetAfter > offsetBefore) {
601 mStreamOffset += (offsetAfter - offsetBefore);
602 } else if (mSuspendCount == 0) {
603 //
604 // possible infinite loop if we continue pumping data!
605 //
606 // NOTE: although not allowed by nsIStreamListener, we
607 // will allow the ODA impl to Suspend the pump. IMAP
608 // does this :-(
609 //
610 NS_ERROR("OnDataAvailable implementation consumed no data")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "OnDataAvailable implementation consumed no data"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 610); MOZ_PretendNoReturn(); } while (0)
;
611 mStatus = NS_ERROR_UNEXPECTED;
612 }
613 } else {
614 mStreamOffset += odaAvail; // assume ODA behaved well
615 }
616 }
617 }
618
619 // an error returned from Available or OnDataAvailable should cause us to
620 // abort; however, we must not stop on mStatus if already canceled.
621
622 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
623 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
624 mStatus = rv;
625 } else if (avail) {
626 // if stream is now closed, advance to STATE_STOP right away.
627 // Available may return 0 bytes available at the moment; that
628 // would not mean that we are done.
629 // XXX async streams should have a GetStatus method!
630 rv = mAsyncStream->Available(&avail);
631 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return STATE_TRANSFER;
632 if (rv != NS_BASE_STREAM_CLOSED) mStatus = rv;
633 }
634 }
635 return STATE_STOP;
636}
637
638nsresult nsInputStreamPump::CallOnStateStop() {
639 RecursiveMutexAutoLock lock(mMutex);
640
641 MOZ_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "CallOnStateStop should only be called on the main thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "CallOnStateStop should only be called on the main thread."
")"); do { *((volatile int*)__null) = 642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
642 "CallOnStateStop should only be called on the main thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "CallOnStateStop should only be called on the main thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "CallOnStateStop should only be called on the main thread."
")"); do { *((volatile int*)__null) = 642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
643
644 mState = OnStateStop();
645 return NS_OK;
646}
647
648uint32_t nsInputStreamPump::OnStateStop() {
649 mMutex.AssertCurrentThreadIn();
650
651 if (!NS_IsMainThread() && !mOffMainThread) {
652 // This method can be called on a different thread if nsInputStreamPump
653 // is used off the main-thread.
654 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && mListener &&
655 mozilla::StaticPrefs::network_send_OnDataFinished_nsInputStreamPump()) {
656 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
657 do_QueryInterface(mListener);
658 if (retargetableListener) {
659 retargetableListener->OnDataFinished(mStatus);
660 }
661 }
662 nsresult rv = mLabeledMainThreadTarget->Dispatch(
663 mozilla::NewRunnableMethod("nsInputStreamPump::CallOnStateStop", this,
664 &nsInputStreamPump::CallOnStateStop));
665 NS_ENSURE_SUCCESS(rv, STATE_DEAD)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "STATE_DEAD", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 665); return STATE_DEAD; } } while (false)
;
666 return STATE_DEAD;
667 }
668
669 AUTO_PROFILER_LABEL("nsInputStreamPump::OnStateStop", NETWORK)mozilla::AutoProfilerLabel raiiObject669( "nsInputStreamPump::OnStateStop"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
670
671 LOG((" OnStateStop [this=%p status=%" PRIx32"x" "]\n", this,
672 static_cast<uint32_t>(mStatus)));
673
674 // if an error occurred, we must be sure to pass the error onto the async
675 // stream. in some cases, this is redundant, but since close is idempotent,
676 // this is OK. otherwise, be sure to honor the "close-when-done" option.
677
678 if (!mAsyncStream || !mListener) {
679 MOZ_ASSERT(mAsyncStream, "null mAsyncStream: OnStateStop called twice?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncStream))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAsyncStream" " ("
"null mAsyncStream: OnStateStop called twice?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncStream"
") (" "null mAsyncStream: OnStateStop called twice?" ")"); do
{ *((volatile int*)__null) = 679; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
680 MOZ_ASSERT(mListener, "null mListener: OnStateStop called twice?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mListener))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mListener" " (" "null mListener: OnStateStop called twice?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 680); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mListener" ") ("
"null mListener: OnStateStop called twice?" ")"); do { *((volatile
int*)__null) = 680; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
681 return STATE_DEAD;
682 }
683
684 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
685 mAsyncStream->CloseWithStatus(mStatus);
686 } else if (mCloseWhenDone) {
687 mAsyncStream->Close();
688 }
689
690 mAsyncStream = nullptr;
691 mIsPending = false;
692 {
693 // We're on the writing thread.
694 // We believe that mStatus can't be changed on us here.
695 AssertOnThread();
696
697 nsCOMPtr<nsIStreamListener> listener = mListener;
698 nsresult status = mStatus;
699 // Note: Must exit mutex for call to OnStartRequest to avoid
700 // deadlocks when calls to RetargetDeliveryTo for multiple
701 // nsInputStreamPumps are needed (e.g. nsHttpChannel).
702 RecursiveMutexAutoUnlock unlock(mMutex);
703
704 listener->OnStopRequest(this, status);
705 }
706 mTargetThread = nullptr;
707 mListener = nullptr;
708
709 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
710
711 return STATE_DEAD;
712}
713
714nsresult nsInputStreamPump::CreateBufferedStreamIfNeeded() {
715 if (mAsyncStreamIsBuffered) {
716 return NS_OK;
717 }
718
719 // ReadSegments is not available for any nsIAsyncInputStream. In order to use
720 // it, we wrap a nsIBufferedInputStream around it, if needed.
721
722 if (NS_InputStreamIsBuffered(mAsyncStream)) {
723 mAsyncStreamIsBuffered = true;
724 return NS_OK;
725 }
726
727 nsCOMPtr<nsIInputStream> stream;
728 nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(stream),
729 mAsyncStream.forget(), 4096);
730 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 730); return rv; } } while (false)
;
731
732 // A buffered inputStream must implement nsIAsyncInputStream.
733 mAsyncStream = do_QueryInterface(stream);
734 MOZ_DIAGNOSTIC_ASSERT(mAsyncStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncStream))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAsyncStream", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 734); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAsyncStream"
")"); do { *((volatile int*)__null) = 734; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
735 mAsyncStreamIsBuffered = true;
736
737 return NS_OK;
738}
739
740//-----------------------------------------------------------------------------
741// nsIThreadRetargetableRequest
742//-----------------------------------------------------------------------------
743
744NS_IMETHODIMPnsresult
745nsInputStreamPump::RetargetDeliveryTo(nsISerialEventTarget* aNewTarget) {
746 RecursiveMutexAutoLock lock(mMutex);
747
748 NS_ENSURE_ARG(aNewTarget)do { if ((__builtin_expect(!!(!(aNewTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNewTarget" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 748); return NS_ERROR_INVALID_ARG; } } while (false)
;
749 NS_ENSURE_TRUE(mState == STATE_START || mState == STATE_TRANSFER,do { if ((__builtin_expect(!!(!(mState == STATE_START || mState
== STATE_TRANSFER)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"mState == STATE_START || mState == STATE_TRANSFER" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 750); return NS_ERROR_UNEXPECTED; } } while (false)
750 NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mState == STATE_START || mState
== STATE_TRANSFER)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"mState == STATE_START || mState == STATE_TRANSFER" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 750); return NS_ERROR_UNEXPECTED; } } while (false)
;
751
752 // If canceled, do not retarget. Return with canceled status.
753 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
754 return mStatus;
755 }
756
757 if (aNewTarget == mTargetThread) {
758 NS_WARNING("Retargeting delivery to same thread")NS_DebugBreak(NS_DEBUG_WARNING, "Retargeting delivery to same thread"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/base/nsInputStreamPump.cpp"
, 758)
;
759 return NS_OK;
760 }
761
762 if (mOffMainThread) {
763 // Don't support retargeting if this pump is already used off the main
764 // thread.
765 return NS_ERROR_FAILURE;
766 }
767
768 // Ensure that |mListener| and any subsequent listeners can be retargeted
769 // to another thread.
770 nsresult rv = NS_OK;
771 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
772 do_QueryInterface(mListener, &rv);
773 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && retargetableListener) {
774 rv = retargetableListener->CheckListenerChain();
775 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
776 mTargetThread = aNewTarget;
777 mRetargeting = true;
778 }
779 }
780 LOG(
781 ("nsInputStreamPump::RetargetDeliveryTo [this=%p aNewTarget=%p] "
782 "%s listener [%p] rv[%" PRIx32"x" "]",
783 this, aNewTarget, (mTargetThread == aNewTarget ? "success" : "failure"),
784 (nsIStreamListener*)mListener, static_cast<uint32_t>(rv)));
785 return rv;
786}
787
788NS_IMETHODIMPnsresult
789nsInputStreamPump::GetDeliveryTarget(nsISerialEventTarget** aNewTarget) {
790 RecursiveMutexAutoLock lock(mMutex);
791
792 nsCOMPtr<nsISerialEventTarget> target = mTargetThread;
793 target.forget(aNewTarget);
794 return NS_OK;
795}