Closed Bug 192478 Opened 22 years ago Closed 22 years ago

mozilla freezes when 'View Selection Source' @ nsPipe3.cpp::nsPipeOutputStream::WriteSegments

Categories

(Core :: Networking, defect, P1)

x86
All
defect

Tracking

()

RESOLVED FIXED
mozilla1.3final

People

(Reporter: gunnar.kaestle, Assigned: darin.moz)

References

()

Details

(Keywords: hang, Whiteboard: fixed1.3)

Attachments

(1 file)

User-Agent: Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.3b) Gecko/20030201 Build Identifier: Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.3b) Gecko/20030201 I found a document (using_priv_help.html), which freezes the Mozilla window when asking for the sourcecode of a selected part. Reproducible: Always Steps to Reproduce: 1. Start Mozilla 2. Open URL as given above 3. Mark section 'Using the Cookie Manager ... ... and sends them back to the web site.' 4. Right-click and choose 'View Selection Source' Actual Results: Mozilla windows dont work, they are not addressable and display nothing. Mozilla process has to be terminated. Expected Results: Show the source code of the selected section.
Confirming on Win2k with trunk build 2003020708. OS -> All Not sure about Component.
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Linux → All
It's enough to highlight just the "r" in "Using the Cookie Manager" and the "A" at the start of the next paragraph....
Assignee: mjudge → doron
Severity: normal → critical
Component: Selection → ViewSource
Keywords: hang
To rbs....
Assignee: doron → rbs
This is due to a bug in necko. View Selection Source does: getBrowser().webNavigation .loadURI("view-source:data:text/html;charset=utf-8," + escape(tmpNode.innerHTML), loadFlags, null, null, null); and it is hanging when loadURI() is doing its work. Below is the precise spot where the hang occurs, followed by the complete stack trace. NS_IMETHODIMP nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count, PRUint32 *writeCount) { LOG(("OOO WriteSegments [this=%x count=%u]\n", this, count)); nsresult rv = NS_OK; char *segment; PRUint32 segmentLen; *writeCount = 0; while (count) { rv = mPipe->GetWriteSegment(segment, segmentLen); if (NS_FAILED(rv)) { if (rv == NS_BASE_STREAM_WOULD_BLOCK) { // pipe is full if (!mBlocking) { // ignore this error if we've already written something if (*writeCount > 0) rv = NS_OK; break; } // wait for the pipe to have an empty segment. HANG HERE>>>>>> rv = Wait(); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if (NS_SUCCEEDED(rv)) continue; } mPipe->OnPipeException(rv); break; } // write no more than count if (segmentLen > count) segmentLen = count; PRUint32 readCount, originalLen = segmentLen; while (segmentLen) { readCount = 0; rv = reader(this, closure, segment, *writeCount, segmentLen, &readCount); if (NS_FAILED(rv) || (readCount == 0)) { count = 0; // any errors returned from the reader end here: do not // propogate to the caller of WriteSegments. rv = NS_OK; break; } segment += readCount; segmentLen -= readCount; count -= readCount; *writeCount += readCount; mLogicalOffset += readCount; } if (segmentLen < originalLen) mPipe->AdvanceWriteCursor(originalLen - segmentLen); } return rv; } STACK TRACE =========== nsPipeOutputStream::WriteSegments(nsPipeOutputStream * const 0x03da99a0, unsigned int (nsIOutputStream *, void *, char *, unsigned int, unsigned int, unsigned int *)* 0x0523c390 nsReadData(nsIOutputStream *, void *, char *, unsigned int, unsigned int, unsigned int *), void * 0x03da9bd0, unsigned int 36763, unsigned int * 0x0012c804) line 1029 nsDataChannel::ParseData() line 239 + 49 bytes nsDataChannel::Init(nsIURI * 0x03df7fb0) line 82 + 8 bytes nsDataHandler::NewChannel(nsDataHandler * const 0x03dc91f0, nsIURI * 0x03df7fb0, nsIChannel * * 0x03df7c7c) line 127 + 12 bytes nsIOService::NewChannelFromURI(nsIOService * const 0x00f7f2c8, nsIURI * 0x03df7fb0, nsIChannel * * 0x03df7c7c) line 460 + 40 bytes nsIOService::NewChannel(nsIOService * const 0x00f7f2c8, const nsACString & {...}, const char * 0x00000000, nsIURI * 0x00000000, nsIChannel * * 0x03df7c7c) line 473 + 25 bytes nsViewSourceChannel::Init(nsIURI * 0x03df7980) line 76 + 70 bytes nsViewSourceHandler::NewChannel(nsViewSourceHandler * const 0x03d37f58, nsIURI * 0x03df7980, nsIChannel * * 0x0012cb18) line 124 + 12 bytes nsIOService::NewChannelFromURI(nsIOService * const 0x00f7f2c8, nsIURI * 0x03df7980, nsIChannel * * 0x0012cb18) line 460 + 40 bytes NS_NewChannel(nsIChannel * * 0x0012cc34, nsIURI * 0x03df7980, nsIIOService * 0x00f7f2c8, nsILoadGroup * 0x03c35320, nsIInterfaceRequestor * 0x03bff758, unsigned int 524288) line 163 + 20 bytes nsDocShell::DoURILoad(nsIURI * 0x03df7980, nsIURI * 0x00000000, nsISupports * 0x03c3c238, nsIInputStream * 0x00000000, nsIInputStream * 0x00000000, int 1, nsIDocShell * * 0x00000000, nsIRequest * * 0x00000000) line 5233 + 91 bytes nsDocShell::InternalLoad(nsDocShell * const 0x03bff730, nsIURI * 0x03df7980, nsIURI * 0x00000000, nsISupports * 0x00000000, int 1, const unsigned short * 0x03cd5330, nsIInputStream * 0x00000000, nsIInputStream * 0x00000000, unsigned int 1, nsISHEntry * 0x00000000, int 1, nsIDocShell * * 0x00000000, nsIRequest * * 0x00000000) line 5147 + 51 bytes nsDocShell::LoadURI(nsDocShell * const 0x03bff730, nsIURI * 0x03df7980, nsIDocShellLoadInfo * 0x03df79e8, unsigned int 0, int 1) line 725 + 80 bytes nsDocShell::LoadURI(nsDocShell * const 0x03bff740, const unsigned short * 0x04230068, unsigned int 256, nsIURI * 0x00000000, nsIInputStream * 0x00000000, nsIInputStream * 0x00000000) line 2450 + 41 bytes XPTC_InvokeByIndex(nsISupports * 0x03bff740, unsigned int 8, unsigned int 5, nsXPTCVariant * 0x0012d370) line 102 XPCWrappedNative::CallMethod(XPCCallContext & {...}, XPCWrappedNative::CallMode CALL_METHOD) line 2023 + 42 bytes XPC_WN_CallMethod(JSContext * 0x039cece0, JSObject * 0x03c01ef8, unsigned int 5, long * 0x03c631ac, long * 0x0012d64c) line 1292 + 14 bytes js_Invoke(JSContext * 0x039cece0, unsigned int 5, unsigned int 0) line 839 + 23 bytes js_Interpret(JSContext * 0x039cece0, long * 0x0012e494) line 2803 + 15 bytes js_Invoke(JSContext * 0x039cece0, unsigned int 1, unsigned int 2) line 856 + 13 bytes js_InternalInvoke(JSContext * 0x039cece0, JSObject * 0x033ce790, long 60499184, unsigned int 0, unsigned int 1, long * 0x0012e6f0, long * 0x0012e5c0) line 931 + 20 bytes JS_CallFunctionValue(JSContext * 0x039cece0, JSObject * 0x033ce790, long 60499184, unsigned int 1, long * 0x0012e6f0, long * 0x0012e5c0) line 3431 + 31 bytes nsJSContext::CallEventHandler(nsJSContext * const 0x038606f8, void * 0x033ce790, void * 0x039b24f0, unsigned int 1, void * 0x0012e6f0, int * 0x0012e6f4, int 0) line 1040 + 33 bytes nsJSEventListener::HandleEvent(nsJSEventListener * const 0x0390d9b8, nsIDOMEvent * 0x03c3caf8) line 181 + 77 bytes nsEventListenerManager::HandleEventSubType(nsListenerStruct * 0x0390da78, nsIDOMEvent * 0x03c3caf8, nsIDOMEventTarget * 0x039f71e0, unsigned int 1, unsigned int 7) line 1216 + 20 bytes nsEventListenerManager::HandleEvent(nsEventListenerManager * const 0x038858e0, nsIPresContext * 0x03882f00, nsEvent * 0x0012ee2c, nsIDOMEvent * * 0x0012ede8, nsIDOMEventTarget * 0x039f71e0, unsigned int 7, nsEventStatus * 0x0012ee54) line 1898 + 36 bytes GlobalWindowImpl::HandleDOMEvent(GlobalWindowImpl * const 0x039f71d0, nsIPresContext * 0x03882f00, nsEvent * 0x0012ee2c, nsIDOMEvent * * 0x0012ede8, unsigned int 7, nsEventStatus * 0x0012ee54) line 805 DocumentViewerImpl::LoadComplete(DocumentViewerImpl * const 0x03891400, unsigned int 0) line 936 + 47 bytes nsDocShell::EndPageLoad(nsIWebProgress * 0x03afc804, nsIChannel * 0x03ac63e8, unsigned int 0) line 4278 nsWebShell::EndPageLoad(nsIWebProgress * 0x03afc804, nsIChannel * 0x03ac63e8, unsigned int 0) line 774 nsDocShell::OnStateChange(nsDocShell * const 0x03afc67c, nsIWebProgress * 0x03afc804, nsIRequest * 0x03ac63e8, unsigned int 131088, unsigned int 0) line 4210 nsDocLoaderImpl::FireOnStateChange(nsIWebProgress * 0x03afc804, nsIRequest * 0x03ac63e8, int 131088, unsigned int 0) line 1230 nsDocLoaderImpl::doStopDocumentLoad(nsIRequest * 0x03ac63e8, unsigned int 0) line 867 nsDocLoaderImpl::DocLoaderIsEmpty() line 765 nsDocLoaderImpl::DocLoaderIsEmpty() line 768 nsDocLoaderImpl::OnStopRequest(nsDocLoaderImpl * const 0x03c350dc, nsIRequest * 0x03c35868, nsISupports * 0x00000000, unsigned int 0) line 695 nsLoadGroup::RemoveRequest(nsLoadGroup * const 0x03c35320, nsIRequest * 0x03c35868, nsISupports * 0x00000000, unsigned int 0) line 694 + 35 bytes nsInputStreamChannel::OnStopRequest(nsInputStreamChannel * const 0x03c3586c, nsIRequest * 0x03c35980, nsISupports * 0x00000000, unsigned int 0) line 357 nsInputStreamPump::OnStateStop() line 462 nsInputStreamPump::OnInputStreamReady(nsInputStreamPump * const 0x03c35984, nsIAsyncInputStream * 0x03c35a6c) line 320 + 11 bytes nsInputStreamReadyEvent::EventHandler(PLEvent * 0x039dcfb4) line 102 PL_HandleEvent(PLEvent * 0x039dcfb4) line 663 + 10 bytes PL_ProcessPendingEvents(PLEventQueue * 0x00f33e20) line 593 + 9 bytes nsEventQueueImpl::ProcessPendingEvents(nsEventQueueImpl * const 0x00ef93b0) line 387 + 12 bytes nsWindow::DispatchPendingEvents() line 3729 nsWindow::ProcessMessage(unsigned int 512, unsigned int 0, long 15270082, long * 0x0012fc38) line 4072 nsWindow::WindowProc(HWND__ * 0x00a003d4, unsigned int 512, unsigned int 0, long 15270082) line 1402 + 27 bytes USER32! 77e148dc() USER32! 77e14aa7() USER32! 77e14bf7() nsAppShellService::Run(nsAppShellService * const 0x0157a718) line 480 main1(int 1, char * * 0x00270060, nsISupports * 0x00ef5468) line 1273 + 32 bytes main(int 1, char * * 0x00270060) line 1636 + 37 bytes mainCRTStartup() line 338 + 17 bytes KERNEL32! 77e992a6() BTW, to debug this, I just added a break point and stepped in the debugger: =========================================================================== NS_IMETHODIMP nsDocShell::LoadURI(const PRUnichar * aURI, PRUint32 aLoadFlags, nsIURI * aReferingURI, nsIInputStream * aPostStream, nsIInputStream * aHeaderStream) { nsAutoString tmp(aURI); if (tmp.Find(NS_LITERAL_STRING("view-source:data")) >= 0) NS_ASSERTION(0,"XXXrbs break - nsDocShell::LoadURI"); [...] }
darin?
Helpful short-cut to save debugging time: assuming you select 'r' and 'A' (comment 2) and View Selection Source with that, you can quickly leap-frog to where/when the hang occurs, by just adding this break-point in nsPipeOutputStream::WriteSegments() in xpcom\io\nsPipe3.cpp: *writeCount = 0; while (count) { if (count == 36763) NS_ASSERTION(0, "will hang"); [...] }
Bug 161511 shares some similarities with this one, with the top of the stack traces all pointing at nsPipe::nsPipeInputStream::ReadSegments(). Maybe this bug is going to shed some light into what is happening.
-> necko
Assignee: rbs → darin
Component: ViewSource → Networking
Summary: mozilla freezes when 'View Selection Source' → mozilla freezes when 'View Selection Source' @ nsPipe3.cpp::nsPipeOutputStream::WriteSegments
I have similar symptoms at: http://www.hyperorg.com/backissues/joho-feb14-03.html#class if I highlight from "Individuality, Society and Self: ..." to "... is a really good book. Wish I had read it sooner.)" and View Selection Source, it locks up. This happened with Windows 98 and 2000 Mozilla 1.3b.
Here's what's going on: 1) The data: channel instantiates a pipe using NS_NewPipe with no params. This means blocking input, blocking output, default maximum size (which happens to be 4096*16 == 65536 bytes). 2) The data channel writes all the data for the data: url to this pipe. For the case we're looking at that's 97880 bytes when I tried it. (Selection across two kids of <body> means we're serializing the source of the whole page into that data: url) 3) Since the pipe is blocking, it blocks when there are 97880 - 65536 == 32344 bytes left to write. So now we've blocked on the UI thread. Since no one is reading from the input end of the pipe yet, we're blocked _permanently_ on the UI thread. Congrats, a hang. ;) One simple fix would be to just make the pipe be a max size of PR_UINT32_MAX instead of the default max size. Another simple fix would be that blocking pipes should default to the max possible size instead of 65536 bytes. In addition to any or both of those, we should also think about possible ways to not move these huge gobs of data about in the data: channel....
QA Contact: pmac → benc
Flags: blocking1.3?
Flags: blocking1.3? → blocking1.3+
Status: NEW → ASSIGNED
Priority: -- → P1
Target Milestone: --- → mozilla1.3final
hmm... so, this appears as a regression since the default pipe size used to be 1MB, and is now only 64k. the data channel should use an unbounded pipe.
Attached patch v1 patchSplinter Review
make data channel use an unbounded pipe w/ necko's recycling allocator.
Attachment #114605 - Flags: superreview?(bzbarsky)
Attachment #114605 - Flags: review?(dougt)
Comment on attachment 114605 [details] [diff] [review] v1 patch OK, that works.
Attachment #114605 - Flags: superreview?(bzbarsky) → superreview+
bz: i went with the "simpler" solution because really, pipes are intended to have a limited size. there is usually a reader and a writer. so, it makes sense to keep the default limits bounded at something reasonable.
Attachment #114605 - Flags: review?(dougt) → review+
Attachment #114605 - Flags: approval1.3?
Yeah, makes sense. I stand by my earlier "we should try to make nsDataChannel not suck so much" suggestion, though... Do we have a streaming base64 decoder we could use instead of what we do now? If so, we may be able to switch to decoding and delivering the data in byte-size chunks on request.....
bz: no, i don't think we have a streaming base64 decoder... though i wonder if mailnews doesn't have one.
fixed-on-trunk
Status: ASSIGNED → RESOLVED
Closed: 22 years ago
Resolution: --- → FIXED
did this break os/2?
I would think that just encoding chunks of data with PL_Base64Encode or what that's called, and later decoding them again, would work ok...
It's decoding, and doesn't base64 use multibyte sequences that could cross buffer boundaries?
if you always read multiples of 4 bytes, you should be ok, because 3 source bytes get encoded to 4 encoded bytes.
Wanna write a patch? ;)
Whiteboard: fixed1.3
while that would help for b64 data, it would not help for textual data, which is also written as a single block of data into the pipe.
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: