[
https://issues.apache.org/jira/browse/COUCHDB-2834?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14943646#comment-14943646
]
Nick Vatamaniuc commented on COUCHDB-2834:
------------------------------------------
After a bit of investigation, it seems Connection: close header gets set
because we tell mochiweb that we have read all the attachments parts a bit too
late.
The gruesome details:
Mochiweb uses process dictionary value ?SAVE_RECV in should_close() function,
to determine if connection should close. That value should be set after the
body of the request has been read. should_close() is called 3 times per
request lifetime 1) when checking if request is 1.0 HTTP, 2) during building
of response headers, 3) and after request finished to see if socket actually
needs closed.
The first two calls to should_close() return true, then final calls return
false. But, by that time, response had already been sent with "Connection:
close" headers.
Couch code put()s that value in function WaitFun. WaitFun() called here, but
after response had already been sent:
https://github.com/apache/couchdb-chttpd/blob/master/src/chttpd_db.erl#L768
WaitFun is defined here
https://github.com/apache/couchdb-couch/blob/master/src/couch_doc.erl#L491)
Calling WaitFun() before send_update_doc in chttpd_db.erl, doesn't work as it
blocks. However putting erlang:put(mochiweb_request_recv, true) does the
trick.
In fact there is a ticket and fix that solved this a while back -- COUCHDB-864
, but then code updated to optimize attachment reading using multiple parser
instances? (I maybe be wrong here) and it was moved to WaitFun.
The tests didn't break immediately because, it seems ibrowse had a bug where it
ignored the Connection: close header. Using a raw tcp socket a python script --
sent request once, got 201 response with "close" ignore it, and sent request
again -- also gets 201 response. Header is set but socket is not closed. That
is because should_close when called after the request finally returned false
and the socket never closed. ibrowse was then fixed to properly close the
socket when it gets "Connection: close" and that is when the bug was revealed.
Need to determine if setting: {code} erlang:put(mochiweb_request_recv, true),
{code} right after {code}receive {doc_bytes, Ref, DocBytes} {code} is the
right approach.
> Server sends connection: close too early
> ----------------------------------------
>
> Key: COUCHDB-2834
> URL: https://issues.apache.org/jira/browse/COUCHDB-2834
> Project: CouchDB
> Issue Type: Bug
> Security Level: public(Regular issues)
> Reporter: Nick Vatamaniuc
>
> This is related COUCHDB-2833.
> This was found investigating the failure of replication tests. Specifically
> couch_replicator_large_atts_tests, the {local, remote} sub-case.
> The test sets up push replications from local to remote.
> Replication workers have more than 1 document larger than
> MAX_BULK_ATT_SIZE=64K. They start pushing them to the target, using a
> keep-alive connection (default for HTTP 1.1), the first few pipelined
> requests will go through using the same connection, then server will accept
> the first PUT to …/docid?edits=false, then return Connection:close and close
> the connection after the 201 Created result.
> Server should not close request too early and instead keep it open longer.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)