First Issue:
INFO: An error occurred in processing while on a non-container thread.
The connection will be closed immediately
Ans:
The async.Stockticker
thread crashed due to a non handled ISE. This explains the behaviour. The exception is logged to the console only. It is not logged into Tomcat log files.
It is a bug with error handling for Tomcat. It is not a regression from recent changes. It is reproducible with Tomcat 7.0.59
.
It is already fixed in trunk 8.0.x (for 8.0.21 onwards)
and 7.0.x (for 7.0.60 onwards)
. So you can upgrade your tomcat version. Then this info message will not be shown.
Resource Link:
Bug 57683 - Crash of stockticket async example caused by an aborted client request
Second Issue:
java.net.SocketException: Broken pipe
Solution-1:
This problem actually occurs when we missed to close the connections like URLConnection and close various open streams. I want to share an example
Before:
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Lorem ipsum...");
out.close();
After:
OutputStream os = urlConnection.getOutputStream();
OutputStream out = new BufferedOutputStream(os);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Lorem ipsum...");
bw.close(); //This is must. If you miss to close, then "java.net.SocketException: Broken pipe" error comes
out.close();
os.close();
Solution-2:
When we want to load testing in our app server, sometimes this error occurs.
The data takes a long time to be generated
and the load testing tool does not wait for the large amounts of data
long enough then it closes the connection. Actually low memory caused the application to close the receiving socket or indeed exit altogether, with the same effect.
If we add additional memory to our JVM, then it resolved the issue.
Solution-3:
As @EJP suggested,
This is caused by writing to a connection when the other end has already closed it.
So you have a poorly defined or implemented application protocol. if this is happening there is something wrong with your application protocol specification or implementation, most probably that you don't even have connection.
If the server side HTTP application is getting Broken Pipe exceptions it just means the client browser has exited/gone to another page/timed out/gone
back in the history/whatever. Just forget about it.
Resource Link:
- How to fix java.net.SocketException: Broken pipe?
- Why a "java.net.SocketException: Broken pipe" will occur?
If you want to reproduce this error, then this tutorial may help you.
Third Issue:
Exception in thread "Thread-28" java.lang.NumberFormatException: For
input string: "boom"
This error occurs when you tried to convert/parse alphabetic string to interger. It is normal java error NumberFormatException
.
UPDATE:
As you have wanted to know that in which cases Tomcat decides to log
that additional message when catching exception that was thrown out of
an application. So I am sharing briefly.
For making a clear conception of "INFO: An error occurred in processing while on a non-container thread. The connection will be closed immediately java.net.SocketException: Broken pipe"
, First I want to share with you that it is socket related issue. There are 6 SocketEvent in tomcat. They are OPEN_READ, OPEN_WRITE, STOP, TIMEOUT, DISCONNECT and ERROR
. These occur per socket that require further processing by the container. Usually these events are triggered by the socket implementation but they may be triggered by the container also.
Socket Event "ERROR":
An error has occurred on a non-container thread and processing needs to return to the container for any necessary clean-up. Examples of where this is used include:
- by NIO2 to signal the failure of a completion handler
- by the container to signal an I/O error on a non-container thread during Servlet 3.0 asynchronous processing.
When this error occurs and INFO message is shown in TOMCAT?
This is the code snapshot where the info message comes.
/**
* Update the current error state to the new error state if the new error
* state is more severe than the current error state.
* @param errorState The error status details
* @param t The error which occurred
*/
protected void setErrorState(ErrorState errorState, Throwable t) {
boolean blockIo = this.errorState.isIoAllowed() && !errorState.isIoAllowed();
this.errorState = this.errorState.getMostSevere(errorState);
if (blockIo && !ContainerThreadMarker.isContainerThread() && isAsync()) {
// The error occurred on a non-container thread during async
// processing which means not all of the necessary clean-up will
// have been completed. Dispatch to a container thread to do the
// clean-up. Need to do it this way to ensure that all the necessary
// clean-up is performed.
if (response.getStatus() < 400) {
response.setStatus(500);
}
getLog().info(sm.getString("abstractProcessor.nonContainerThreadError"), t); // This section gives the INFO message "INFO: An error occurred in processing while on a non-container thread. The connection will be closed immediately"
socketWrapper.processSocket(SocketEvent.ERROR, true);
}
}
How DEADLOCK may occur?
When a request uses a sequence of multiple start(); dispatch()
with non-container threads it is possible for a previous dispatch()
to interfere with a following start()
. This lock prevents that from happening. It is a dedicated object as user code may lock on the AsyncContext so if container code also locks on that object deadlocks may occur.
How non-container thread defines current error state and gives response?
With the introduction of async processing and the possibility of non-container threads calling sendError() tracking the current error state
and ensuring that the correct error page is called becomes more complicated. This state attribute helps by tracking the current error state and informing callers that attempt to change state if the change was successful or if another thread got there first.
/**
* The state machine is very simple:
*
* 0 - NONE
* 1 - NOT_REPORTED
* 2 - REPORTED
*
*
* -->---->-- >NONE
* | | |
* | | | setError()
* ^ ^ |
* | | \|/
* | |-<-NOT_REPORTED
* | |
* ^ | report()
* | |
* | \|/
* |----<----REPORTED
*
*/
When executeNonBlockingDispatches(...) method is called in a non-container thread and how it interacts with SocketWrapper?
This method is called when non-blocking IO is initiated by defining a read and/or write listener in a non-container thread. It is called once the non-container thread completes so that the first calls to onWritePossible()
and/or onDataAvailable()
as appropriate are made by the container.
Processing the dispatches requires (for APR/native at least)
that the socket has been added to the waitingRequests queue. This may not have occurred by the time that the non-container thread completes triggering the call to this method. Therefore, the coded syncs on the SocketWrapper as the container thread that initiated this non-container thread holds a lock on the SocketWrapper. The container thread will add the socket to the waitingRequests queue before releasing the lock on the socketWrapper. Therefore, by obtaining the lock on socketWrapper before processing the dispatches, we can be sure that the socket has been added to the waitingRequests queue
.