bitcoin/test/functional/test_framework
Wladimir J. van der Laan a88bd3186d
Merge #14670: http: Fix HTTP server shutdown
28479f926f qa: Test bitcond shutdown (João Barbosa)
8d3f46ec39 http: Remove timeout to exit event loop (João Barbosa)
e98a9eede2 http: Remove unnecessary event_base_loopexit call (João Barbosa)
6b13580f4e http: Unlisten sockets after all workers quit (João Barbosa)
18e9685816 http: Send "Connection: close" header if shutdown is requested (João Barbosa)
02e1e4eff6 rpc: Add wait argument to stop (João Barbosa)

Pull request description:

  Fixes #11777. Reverts #11006. Replaces #13501.

  With this change the HTTP server will exit gracefully, meaning that all requests will finish processing and sending the response, even if this means to wait more than 2 seconds (current time allowed to exit the event loop).

  Another small change is that connections are accepted even when the server is stopping, but HTTP requests are rejected. This can be improved later, especially if chunked replies are implemented.

  Briefly, before this PR, this is the order or events when a request arrives (RPC `stop`):
   1. `bufferevent_disable(..., EV_READ)`
   2. `StartShutdown()`
   3. `evhttp_del_accept_socket(...)`
   4. `ThreadHTTP` terminates (event loop exits) because there are no active or pending events thanks to 1. and 3.
   5. client doesn't get the response thanks to 4.

  This can be verified by applying
  ```diff
       // Event loop will exit after current HTTP requests have been handled, so
       // this reply will get back to the client.
       StartShutdown();
  +    MilliSleep(2000);
       return "Bitcoin server stopping";
   }
  ```
  and checking the log output:
  ```
      Received a POST request for / from 127.0.0.1:62443
      ThreadRPCServer method=stop user=__cookie__
      Interrupting HTTP server
  **  Exited http event loop
      Interrupting HTTP RPC server
      Interrupting RPC
      tor: Thread interrupt
      Shutdown: In progress...
      torcontrol thread exit
      Stopping HTTP RPC server
      addcon thread exit
      opencon thread exit
      Unregistering HTTP handler for / (exactmatch 1)
      Unregistering HTTP handler for /wallet/ (exactmatch 0)
      Stopping RPC
      RPC stopped.
      Stopping HTTP server
      Waiting for HTTP worker threads to exit
      msghand thread exit
      net thread exit

      ... sleep 2 seconds ...

      Waiting for HTTP event thread to exit
      Stopped HTTP server
  ```

  For this reason point 3. is moved right after all HTTP workers quit. In that moment HTTP replies are queued in the event loop which keeps spinning util all connections are closed. In order to trigger the server side close with keep alive connections (implicit in HTTP/1.1) the header `Connection: close` is sent if shutdown was requested. This can be tested by
  ```
  bitcoind -regtest
  nc localhost 18443
  POST / HTTP/1.1
  Authorization: Basic ...
  Content-Type: application/json
  Content-Length: 44

  {"jsonrpc": "2.0","method":"stop","id":123}
  ```

  Summing up, this PR:
   - removes explicit event loop exit — event loop exits once there are no active or pending events
   - changes the moment the listening sockets are removed — explained above
   - sends header `Connection: close` on active requests when shutdown was requested which is relevant when it's a persistent connection (default in HTTP 1.1) — libevent is aware of this header and closes the connection gracefully
   - removes event loop explicit break after 2 seconds timeout

Tree-SHA512: 4dac1e86abe388697c1e2dedbf31fb36a394cfafe5e64eadbf6ed01d829542785a8c3b91d1ab680d3f03f912d14fc87176428041141441d25dcb6c98a1e069d8
2018-12-06 17:43:07 +01:00
..
__init__.py
address.py qa: Run more tests with wallet disabled 2018-09-25 18:08:08 -04:00
authproxy.py tests: Make it possible to run functional tests on Windows 2018-09-17 09:56:49 +08:00
bignum.py
blocktools.py Fix typo in test_framework/blocktools 2018-10-25 09:30:57 +13:00
coverage.py Update copyright headers to 2018 2018-07-27 07:15:02 -04:00
key.py tests: Remove compatibility code not needed now when we're on Python 3 2018-04-16 09:54:27 +02:00
messages.py tests: Remove unused testing code 2018-11-07 18:07:49 +01:00
mininode.py qa: Check specific reject reasons in feature_block 2018-11-13 11:05:24 -05:00
netutil.py tests: Replace usage of tostring() with tobytes() 2018-08-13 19:05:31 -07:00
script.py Add CScriptNum decode python implementation in functional suite 2018-11-29 08:31:48 -05:00
segwit_addr.py
siphash.py Update copyright headers to 2018 2018-07-27 07:15:02 -04:00
socks5.py tests: Remove unused testing code 2018-11-07 18:07:49 +01:00
test_framework.py Merge #14670: http: Fix HTTP server shutdown 2018-12-06 17:43:07 +01:00
test_node.py Merge #14670: http: Fix HTTP server shutdown 2018-12-06 17:43:07 +01:00
util.py [Tests] Rename create_tx and move to blocktools.py 2018-08-09 12:58:35 +02:00