Discussion:
ClientAbortException
Ryan Owens
2005-02-26 19:09:18 UTC
Permalink
In doing a bit of user-error testing, I hit the browsers refresh button
multiple times so that requests would be interrupted.

Doing so logged out the user by throwing an ApplicationRuntimeException
and yielded the following error in the logs:

------------------------
Exception during post-request cleanup.
...
org.apache.catalina.connector.ClientAbortException

java.net.SocketException: Broken pipe
java.net.SocketOutputStream.socketWrite0(Native Method)
...
org.apache.tapestry.request.ResponseOutputStream.forceFlush(ResponseOutp
utStream.java:149)
org.apache.tapestry.engine.AbstractEngine.service(AbstractEngine.java:
928)
...
------------------------

The source code around AbstractEngine.java:928 is:
------------------------
cycle.cleanup();

// Closing the buffered output closes the underlying
stream as well.

if (output != null)
928-->> output.forceFlush();

cleanupAfterRequest(cycle);
------------------------


I can override service and call super.service and catch the
ClientAbortException, but that is a Tomcat specific thing that extends
java.io.IOException,
the service method throws IOException, so I don't see any good
non-tomcat-specific to handle it.

Anyone else hit this?


Thanks,

Ryan Owens


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-***@jakarta.apache.org
For additional commands, e-mail: tapestry-user-***@jakarta.apache.org
matthew c. mead
2005-02-26 20:07:51 UTC
Permalink
I have seen the same issue. In my case, it does not logout the user,
but it prevents my forgetPage() call from having the effect I desire.

If you come up with a solution I'd be interested in hearing it!


-matt
Post by Ryan Owens
In doing a bit of user-error testing, I hit the browsers refresh
button multiple times so that requests would be interrupted.
Doing so logged out the user by throwing an
------------------------
Exception during post-request cleanup.
...
org.apache.catalina.connector.ClientAbortException
java.net.SocketException: Broken pipe
java.net.SocketOutputStream.socketWrite0(Native Method)
...
org.apache.tapestry.request.ResponseOutputStream.forceFlush(ResponseOutp
utStream.java:149)
928)
...
------------------------
------------------------
cycle.cleanup();
// Closing the buffered output closes the underlying
stream as well.
if (output != null)
928-->> output.forceFlush();
cleanupAfterRequest(cycle);
------------------------
I can override service and call super.service and catch the
ClientAbortException, but that is a Tomcat specific thing that
extends java.io.IOException,
the service method throws IOException, so I don't see any good
non-tomcat-specific to handle it.
Anyone else hit this?
Thanks,
Ryan Owens
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-***@jakarta.apache.org
For additional commands, e-mail: tapestry-user-***@jakarta.apache.org
Johan Maasing
2005-02-26 20:57:45 UTC
Permalink
Post by Ryan Owens
In doing a bit of user-error testing, I hit the browsers refresh
button multiple times so that requests would be interrupted.
...
...
Post by Ryan Owens
java.net.SocketException: Broken pipe
java.net.SocketOutputStream.socketWrite0(Native Method)
...
Post by Ryan Owens
I can override service and call super.service and catch the
ClientAbortException, but that is a Tomcat specific thing that
extends java.io.IOException,
the service method throws IOException, so I don't see any good
non-tomcat-specific to handle it.
Anyone else hit this?
I don't have a solution but I can at least say that the basic reason for
this is (as you say) that the request is interrupted. Most servlet
containers will throw a SocketException: Broken pipe in this situation.
The servlet container is in the process of sending output to the client
but the client has already requested another page (the refresh) this
means that the servlet container has nowhere to send the reply, hence
the broken pipe.
Perhaps Tapestry should catch and ignore IOException in the forceFlush
method?

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-***@jakarta.apache.org
For additional commands, e-mail: tapestry-user-***@jakarta.apache.org
Ryan Owens
2005-02-26 21:16:38 UTC
Permalink
Post by Johan Maasing
Post by Ryan Owens
In doing a bit of user-error testing, I hit the browsers refresh
button multiple times so that requests would be interrupted.
...
...
Post by Ryan Owens
java.net.SocketException: Broken pipe
java.net.SocketOutputStream.socketWrite0(Native Method)
...
Post by Ryan Owens
I can override service and call super.service and catch the
ClientAbortException, but that is a Tomcat specific thing that
extends java.io.IOException,
the service method throws IOException, so I don't see any good
non-tomcat-specific to handle it.
Anyone else hit this?
I don't have a solution but I can at least say that the basic reason
for this is (as you say) that the request is interrupted. Most
servlet containers will throw a SocketException: Broken pipe in this
situation. The servlet container is in the process of sending output
to the client but the client has already requested another page (the
refresh) this means that the servlet container has nowhere to send the
reply, hence the broken pipe.
Perhaps Tapestry should catch and ignore IOException in the forceFlush
method?
Tapestry actually does catch it so things don't explode, but the
problem is that it doesn't call cleanupAfterRequest if there's an
error.
That was breaking some of my stuff since I do a lot of cleanup/init.

I ended up overriding AbstractEngine.service , in addition to
setupForRequest and cleanupAfterRequest. I added the RequestContexts
being called to the visit in order to see what was happening. Then at
the end of the service method, I could tell if both begin and cleanup
had been called. If not, I could assume there was a caught Exception
of some kind and go ahead and call my cleanup code which would normally
be called by cleanupAfterRequest..

Turns out this solved a number of subtle problems I was having.
Of course the fact that I am hacking the Engine makes me think I'm
doing something horribly wrong.

Am I?

Thanks

Ryan Owens
Post by Johan Maasing
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-***@jakarta.apache.org
For additional commands, e-mail: tapestry-user-***@jakarta.apache.org
Loading...