https://issues.apache.org/bugzilla/show_bug.cgi?id=55715

            Bug ID: 55715
           Summary: RemoteEndpoint.Async#sendText(String, SendHandler) can
                    cause StackOverflowErrors and contradicts Oracle's
                    JavaDoc
           Product: Tomcat 8
           Version: trunk
          Hardware: PC
            Status: NEW
          Severity: normal
          Priority: P2
         Component: WebSocket
          Assignee: [email protected]
          Reporter: [email protected]

See thread on users list [1]:

Tomcat's current implementation of RemoteEndpoint.Async#sendText(String,
SendHandler) can cause StackOverflowErrors (and seems to contradict Oracle's
JavaDoc).

In Tomcat, Async#sendText(...) seems to implemented so that when it could send
all of the data immediately, then it directly calls SendHandler#onResult(...);
whereas when it couldn't send the data immediately, the SendHandler will be
called from another thread.

Oracle's javadoc for RemoteEndpoint.Async says:

"The completion handlers for the asynchronous methods are always called with a
different thread from that which initiated the send."

Now, imagine the case that you want to send 10000 very small text messages to a
client (very unlikely, but possibly could happen). With synchronous I/O
(RemoteEndpoint.Basic), you would do this in this way:

        RemoteEndpoint.Basic basic = session.getBasicRemote();
        for (int i = 0; i < 10000; i++) {
            basic.sendText("Hi, Count: " + i);
        }

In this case, there is no problem.

Now imagine you want to do this asynchronously (using a Callback to be informed
when sending is completed), then you could do it this way (e.g. put the
following code in onOpen() method of Tomcat's EchoEndpoint example):

        final AtomicInteger aint = new AtomicInteger();
        final RemoteEndpoint.Async async = session.getAsyncRemote();

        SendHandler handler = new SendHandler() {
            @Override
            public void onResult(SendResult result) {
                int nextVal = aint.incrementAndGet();
                if (nextVal < 10000) {
                    async.sendText("Hi, Count: " + nextVal, this);
                }
            }
        };
        async.sendText("Hi, Count: " + aint.get(), handler);

The problem here is that because the messages are very short, Tomcat will be
able to send them immediately, calling the SendHandler#onResult() directly from
Async.sendText(), which will eventually cause a StackOverflowError.

I think if SendHandler#onResult() was always called from a different thread
than the one which calls Async.send... (like the Javadoc says), then although
the performance would probably be worse, StackOverflowErrors shouldn't occur.


[1] http://markmail.org/message/gpxzdwtxtrpynvux

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to