{"action":"created","issue":{"url":"https://api.github.com/repos/gorilla/websocket/issues/176","repository_url":"https://api.github.com/repos/gorilla/websocket","labels_url":"https://api.github.com/repos/gorilla/websocket/issues/176/labels{/name}","comments_url":"https://api.github.com/repos/gorilla/websocket/issues/176/comments","events_url":"https://api.github.com/repos/gorilla/websocket/issues/176/events","html_url":"https://github.com/gorilla/websocket/pull/176","id":185792326,"number":176,"title":"Don't close conn/FD on write errors","user":{"login":"KiranRG","id":9190852,"avatar_url":"https://avatars.githubusercontent.com/u/9190852?v=3","gravatar_id":"","url":"https://api.github.com/users/KiranRG","html_url":"https://github.com/KiranRG","followers_url":"https://api.github.com/users/KiranRG/followers","following_url":"https://api.github.com/users/KiranRG/following{/other_user}","gists_url":"https://api.github.com/users/KiranRG/gists{/gist_id}","starred_url":"https://api.github.com/users/KiranRG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KiranRG/subscriptions","organizations_url":"https://api.github.com/users/KiranRG/orgs","repos_url":"https://api.github.com/users/KiranRG/repos","events_url":"https://api.github.com/users/KiranRG/events{/privacy}","received_events_url":"https://api.github.com/users/KiranRG/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2016-10-27T22:06:09Z","updated_at":"2016-10-28T16:44:51Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/gorilla/websocket/pulls/176","html_url":"https://github.com/gorilla/websocket/pull/176","diff_url":"https://github.com/gorilla/websocket/pull/176.diff","patch_url":"https://github.com/gorilla/websocket/pull/176.patch"},"body":"We have built a \"streaming\" layer atop gorilla-websocket, that essentially buffers messages before writing out to the wire .. and on the other end, we would \"deserialize\" the payload into individual messages before returning to the application.\r\n\r\nOne of the issues we encountered when using gorilla's websocket implementation was in the following scenario -- we have a streaming client and a streaming server, each with read and write \"pumps\"; the client sends \"requests\" to the the server, which the server receives/processes and sends back \"responses\" to. After the server has sent the last of its \"responses\" (including a final \"done\" response) it closes the connection.\r\n\r\nThe client has a write-pump (that's sending requests) and a read-pump (that's reading/receiving responses). Because the server has gone away, the client's write-pump encounters an error when doing a write, and the gorilla layer (in the code-path that I have fixed below) automatically/internally closes the connection/FD -- this effectively wipes out any buffered responses (including the \"done\" response) from the server, which would have otherwise been available to read.\r\n\r\nIn our scenario, the client re-connects to the server and retries until it gets the \"done\" response -- which it fails to see due to the above bug, causing it to be stalled doing retries for a long/indefinite time.\r\n\r\nWhat this fix does is to avoid closing the connection on a write-error -- we leave it to the application/user (of gorilla websocket) to call websocket.Close() when done. In fact, for errors from conn.Write, the current code does simply convey it to the user, but unfortunately the check for a partial-write seems to take precedence (and this check would succeed even for a write-failure), causing it to close the connection any time there is a write-failure.\r\n\r\n\r\nIn our case, for instance, this gives an opportunity for our client's read-pump to be able to \"drain\" out all available messages (\"responses\", including the \"done\" response), before encountering the error (due to the connection closure) and closing the connection.\r\n"},"comment":{"url":"https://api.github.com/repos/gorilla/websocket/issues/comments/256969737","html_url":"https://github.com/gorilla/websocket/pull/176#issuecomment-256969737","issue_url":"https://api.github.com/repos/gorilla/websocket/issues/176","id":256969737,"user":{"login":"garyburd","id":33411,"avatar_url":"https://avatars.githubusercontent.com/u/33411?v=3","gravatar_id":"","url":"https://api.github.com/users/garyburd","html_url":"https://github.com/garyburd","followers_url":"https://api.github.com/users/garyburd/followers","following_url":"https://api.github.com/users/garyburd/following{/other_user}","gists_url":"https://api.github.com/users/garyburd/gists{/gist_id}","starred_url":"https://api.github.com/users/garyburd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/garyburd/subscriptions","organizations_url":"https://api.github.com/users/garyburd/orgs","repos_url":"https://api.github.com/users/garyburd/repos","events_url":"https://api.github.com/users/garyburd/events{/privacy}","received_events_url":"https://api.github.com/users/garyburd/received_events","type":"User","site_admin":false},"created_at":"2016-10-28T16:44:51Z","updated_at":"2016-10-28T16:44:51Z","body":"An error in WriteControl is not stored in writeErr. "}}
{"actor":{"display_login":"garyburd"}}