[ 
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)

Reply via email to