httpserver does not close connections when RejectedExecutionException occurs

Yasumasa Suenaga yasuenag at gmail.com
Thu Nov 10 14:43:29 UTC 2016


Hi,

> I think it best to just handle the specific case of REE, as it done in Yuji’s patch.

Will it be a cause of connection leak if RuntimeException is occurred in handler method?
I think we should catch RuntimeException at least.


>> I think you can use finally statement to close the connection in this case.
>
> I don’t believe that this is possible. The handling of the connection may be
> done in a separate thread, some time after execute() returns.

So I said we need to check the implementation of HTTP connection and dispatcher.


Yasumasa


On 2016/11/10 23:00, Chris Hegarty wrote:
>
>> On 9 Nov 2016, at 12:38, Yasumasa Suenaga <yasuenag at gmail.com> wrote:
>>
>> Hi Yuji,
>>
>>> http://cr.openjdk.java.net/~ykubota/8169358/webrev.01/
>
> I think Yuji’s patch is good as is.
>
>> I think you can use finally statement to close the connection in this case.
>
> I don’t believe that this is possible. The handling of the connection may be
> done in a separate thread, some time after execute() returns. I think it best
> to just handle the specific case of REE, as it done in Yuji’s patch.
>
>> Your patch cannot close the connection when any other runtime exceptions are occurred.
>>
>> However, it is concerned double close if custom handler which is implemented by the user throws runtime exception after closing the connection.
>> IMHO, you need to check the implementation of HTTP connection and dispatcher.
>
> -Chris.
>
>>
>> Thanks,
>>
>> Yasumasa
>>
>>
>> On 2016/11/08 18:53, KUBOTA Yuji wrote:
>>> Hi Chris,
>>>
>>> Thank you for your review and updating this issues on JBS.
>>>
>>> I filed an issue:
>>> https://bugs.openjdk.java.net/browse/JDK-8169358
>>>
>>> I don't assign to me because I'm not a committer.
>>>
>>> 2016-11-08 0:28 GMT+09:00 Chris Hegarty <chris.hegarty at oracle.com>:
>>>>> * patch
>>>>> diff --git
>>>>> a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java
>>>>> b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java
>>>>> --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java
>>>>> +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java
>>>>> @@ -442,10 +442,13 @@
>>>>>                 logger.log (Level.TRACE, "Dispatcher (4)", e1);
>>>>>                 closeConnection(conn);
>>>>>             } catch (IOException e) {
>>>>>                 logger.log (Level.TRACE, "Dispatcher (5)", e);
>>>>>                 closeConnection(conn);
>>>>> +            } catch (RejectedExecutionException e) {
>>>>> +                logger.log (Level.TRACE, "Dispatcher (9)", e);
>>>>> +                closeConnection(conn);
>>>>>             }
>>>>>         }
>>>>>     }
>>>>> _
>>>>>     static boolean debug = ServerConfig.debugEnabled ();
>>>>
>>>>
>>>> This looks ok. I wonder if some of these exceptions could be refactored
>>>> into a catch clause with several exception types?
>>>
>>> Yes, I agree to keep simple. I updated my patch as below.
>>> http://cr.openjdk.java.net/~ykubota/8169358/webrev.01/
>>> Could you review it again?
>>>
>>> Thank you,
>>> Yuji
>>>>
>>>> -Chris.
>>>>
>>>>
>>>>
>>>>> * steps to reproduce
>>>>> 1. java -Djava.util.logging.config.file=logging.properties
>>>>> SmallHttpServer
>>>>> 2. post tcp connections by curl or other ways
>>>>>     e.g.: while true; do curl -XPOST --noproxy 127.0.0.1
>>>>> http://127.0.0.1:8080/; done
>>>>> 3. wait RejectedExecutionException occurs as below and then
>>>>> SmallHttpServer stops by this issue.
>>>>> ----
>>>>> Nov 05, 2016 12:01:48 PM sun.net.httpserver.ServerImpl$Dispatcher run
>>>>> FINER: Dispatcher (7)
>>>>> java.util.concurrent.RejectedExecutionException: Task
>>>>> sun.net.httpserver.ServerImpl$Exchange at 37b50d9e rejected from
>>>>> java.util.concurrent.ThreadPoolExecutor at 1b3178d4[Running, pool size =
>>>>> 1, active threads = 0, queued tasks = 0, completed tasks = 7168]
>>>>>        at
>>>>> java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(java.base/ThreadPoolExecutor.java:2076)
>>>>>        at
>>>>> java.util.concurrent.ThreadPoolExecutor.reject(java.base/ThreadPoolExecutor.java:842)
>>>>>        at
>>>>> java.util.concurrent.ThreadPoolExecutor.execute(java.base/ThreadPoolExecutor.java:1388)
>>>>>        at
>>>>> sun.net.httpserver.ServerImpl$Dispatcher.handle(jdk.httpserver/ServerImpl.java:440)
>>>>>        at
>>>>> sun.net.httpserver.ServerImpl$Dispatcher.run(jdk.httpserver/ServerImpl.java:405)
>>>>>        at java.lang.Thread.run(java.base/Thread.java:844)
>>>>> (SmallHttpServer is stopping by not closing socket)
>>>>> ----
>>>>>
>>>>> *logging.properties
>>>>> handlers = java.util.logging.ConsoleHandler
>>>>> com.sun.net.httpserver.level = FINEST
>>>>> java.util.logging.ConsoleHandler.level = FINEST
>>>>> java.util.logging.ConsoleHandler.formatter =
>>>>> java.util.logging.SimpleFormatter
>>>>>
>>>>> * SmallHttpServer.java
>>>>> import com.sun.net.httpserver.HttpExchange;
>>>>> import com.sun.net.httpserver.HttpHandler;
>>>>> import com.sun.net.httpserver.HttpServer;
>>>>>
>>>>> import java.net.InetSocketAddress;
>>>>> import java.util.Scanner;
>>>>> import java.util.concurrent.LinkedBlockingQueue;
>>>>> import java.util.concurrent.ThreadPoolExecutor;
>>>>> import java.util.concurrent.TimeUnit;
>>>>>
>>>>> public class SmallHttpServer {
>>>>>
>>>>>    public static void main(String[] args) throws Exception {
>>>>>        int POOL_SIZE = 1;
>>>>>        String HOST = args.length < 1 ? "127.0.0.1" : args[0];
>>>>>        int PORT = args.length < 2 ? 8080 : Integer.valueOf(args[1]);
>>>>>
>>>>>        // Setup a minimum thread pool to rise
>>>>> RejectExecutionException in httpserver
>>>>>        ThreadPoolExecutor miniHttpPoolExecutor
>>>>>                = new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE, 0L,
>>>>> TimeUnit.MICROSECONDS,
>>>>>                        new LinkedBlockingQueue<>(1), (Runnable r) -> {
>>>>>                            return new Thread(r);
>>>>>                        });
>>>>>        HttpServer httpServer = HttpServer.create(new
>>>>> InetSocketAddress(HOST, PORT), 0);
>>>>>        httpServer.setExecutor(miniHttpPoolExecutor);
>>>>>
>>>>>        HttpHandler res200handler = (HttpExchange exchange) -> {
>>>>>            exchange.sendResponseHeaders(200, 0);
>>>>>            exchange.close();
>>>>>        };
>>>>>        httpServer.createContext("/", res200handler);
>>>>>
>>>>>        httpServer.start();
>>>>>        // Wait stdin to exit
>>>>>        Scanner in = new Scanner(System.in);
>>>>>        while (in.hasNext()) {
>>>>>            System.out.println(in.nextLine());
>>>>>        }
>>>>>        httpServer.stop(0);
>>>>>        miniHttpPoolExecutor.shutdownNow();
>>>>>    }
>>>>> }
>>>>>
>>>>>
>>>>> Thanks,
>>>>> Yuji
>>>>>
>>>>
>>>
>


More information about the net-dev mailing list