Fix to not call OnStartRequest if channel has been canceled. Bug #31957

This commit is contained in:
warren%netscape.com 2000-04-05 06:46:00 +00:00
Родитель 546ab964f8
Коммит f1f675ff42
3 изменённых файлов: 44 добавлений и 29 удалений

Просмотреть файл

@ -95,7 +95,18 @@ void PR_CALLBACK nsStreamListenerEvent::HandlePLEvent(PLEvent* aEvent)
NS_ASSERTION(nsnull != ev,"null event."); NS_ASSERTION(nsnull != ev,"null event.");
nsresult rv = ev->HandleEvent(); nsresult rv = ev->HandleEvent();
ev->mListener->SetStatus(rv); //
// If the consumer fails, then cancel the transport. This is necessary
// in case where the socket transport is blocked waiting for room in the
// pipe, but the consumer fails without consuming all the data.
//
// Unless the transport is cancelled, it will block forever, waiting for
// the pipe to empty...
//
if (NS_FAILED(rv)) {
nsresult cancelRv = ev->mChannel->Cancel(rv);
NS_ASSERTION(NS_SUCCEEDED(cancelRv), "Cancel failed");
}
} }
void PR_CALLBACK nsStreamListenerEvent::DestroyPLEvent(PLEvent* aEvent) void PR_CALLBACK nsStreamListenerEvent::DestroyPLEvent(PLEvent* aEvent)
@ -193,15 +204,23 @@ nsOnStartRequestEvent::HandleEvent()
("netlibEvent: Handle Start [event=%x]", this)); ("netlibEvent: Handle Start [event=%x]", this));
#endif #endif
nsIStreamObserver* receiver = (nsIStreamObserver*)mListener->GetReceiver(); nsIStreamObserver* receiver = (nsIStreamObserver*)mListener->GetReceiver();
return receiver->OnStartRequest(mChannel, mContext); nsresult status;
nsresult rv = mChannel->GetStatus(&status);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed");
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
rv = receiver->OnStartRequest(mChannel, mContext);
}
else {
NS_WARNING("not calling OnStartRequest");
}
return rv;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsAsyncStreamObserver::OnStartRequest(nsIChannel* channel, nsISupports* context) nsAsyncStreamObserver::OnStartRequest(nsIChannel* channel, nsISupports* context)
{ {
nsresult rv = GetStatus(); nsresult rv;
if (NS_FAILED(rv)) return rv;
nsOnStartRequestEvent* event = nsOnStartRequestEvent* event =
new nsOnStartRequestEvent(this, channel, context); new nsOnStartRequestEvent(this, channel, context);
if (event == nsnull) if (event == nsnull)
@ -273,14 +292,16 @@ nsOnStopRequestEvent::HandleEvent()
("netlibEvent: Handle Stop [event=%x]", this)); ("netlibEvent: Handle Stop [event=%x]", this));
#endif #endif
nsIStreamObserver* receiver = (nsIStreamObserver*)mListener->GetReceiver(); nsIStreamObserver* receiver = (nsIStreamObserver*)mListener->GetReceiver();
nsresult rv = mListener->GetStatus(); nsresult status = NS_OK;
nsresult rv = mChannel->GetStatus(&status);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed");
// //
// If the consumer returned a failure code, then pass it out in the // If the consumer returned a failure code, then pass it out in the
// OnStopRequest(...) notification... // OnStopRequest(...) notification...
// //
if (NS_FAILED(rv)) { if (NS_SUCCEEDED(rv) && NS_FAILED(status)) {
mStatus = rv; mStatus = status;
} }
return receiver->OnStopRequest(mChannel, mContext, mStatus, mMessage); return receiver->OnStopRequest(mChannel, mContext, mStatus, mMessage);
} }
@ -372,25 +393,20 @@ nsOnDataAvailableEvent::HandleEvent()
("netlibEvent: Handle Data [event=%x]", this)); ("netlibEvent: Handle Data [event=%x]", this));
#endif #endif
nsIStreamListener* receiver = (nsIStreamListener*)mListener->GetReceiver(); nsIStreamListener* receiver = (nsIStreamListener*)mListener->GetReceiver();
nsresult rv = mListener->GetStatus(); nsresult status;
nsresult rv = mChannel->GetStatus(&status);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetStatus failed");
// //
// Only send OnDataAvailable(... ) notifications if all previous calls // Only send OnDataAvailable(... ) notifications if all previous calls
// have succeeded... // have succeeded...
// //
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
rv = receiver->OnDataAvailable(mChannel, mContext, rv = receiver->OnDataAvailable(mChannel, mContext,
mIStream, mSourceOffset, mLength); mIStream, mSourceOffset, mLength);
//
// If the consumer fails, then cancel the transport. This is necessary
// in case where the socket transport is blocked waiting for room in the
// pipe, but the consumer fails without consuming all the data.
//
// Unless the transport is cancelled, it will block forever, waiting for
// the pipe to empty...
//
if (NS_FAILED(rv)) {
mChannel->Cancel(rv);
} }
else {
NS_WARNING("not calling OnDataAvailable");
} }
return rv; return rv;
} }
@ -401,9 +417,7 @@ nsAsyncStreamListener::OnDataAvailable(nsIChannel* channel, nsISupports* context
PRUint32 aSourceOffset, PRUint32 aSourceOffset,
PRUint32 aLength) PRUint32 aLength)
{ {
nsresult rv = GetStatus(); nsresult rv;
if (NS_FAILED(rv)) return rv;
nsOnDataAvailableEvent* event = nsOnDataAvailableEvent* event =
new nsOnDataAvailableEvent(this, channel, context); new nsOnDataAvailableEvent(this, channel, context);
if (event == nsnull) if (event == nsnull)

Просмотреть файл

@ -40,7 +40,6 @@ public:
// nsAsyncStreamObserver methods: // nsAsyncStreamObserver methods:
nsAsyncStreamObserver() nsAsyncStreamObserver()
: mStatus(NS_OK)
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
} }
@ -51,13 +50,10 @@ public:
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
nsISupports* GetReceiver() { return mReceiver.get(); } nsISupports* GetReceiver() { return mReceiver.get(); }
nsresult GetStatus() { return mStatus; }
void SetStatus(nsresult value) { if (NS_SUCCEEDED(mStatus)) mStatus = value; }
protected: protected:
nsCOMPtr<nsIEventQueue> mEventQueue; nsCOMPtr<nsIEventQueue> mEventQueue;
nsCOMPtr<nsIStreamObserver> mReceiver; nsCOMPtr<nsIStreamObserver> mReceiver;
nsresult mStatus;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -1367,6 +1367,11 @@ nsSocketTransport::IsPending(PRBool *result)
NS_IMETHODIMP NS_IMETHODIMP
nsSocketTransport::GetStatus(nsresult *status) nsSocketTransport::GetStatus(nsresult *status)
{ {
if (NS_FAILED(mCancelStatus))
*status = mCancelStatus;
else if (mStatus == NS_BASE_STREAM_WOULD_BLOCK)
*status = NS_OK;
else
*status = mStatus; *status = mStatus;
return NS_OK; return NS_OK;
} }