Bug Summary

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