{"action":"created","issue":{"url":"https://api.github.com/repos/masterzen/winrm/issues/35","labels_url":"https://api.github.com/repos/masterzen/winrm/issues/35/labels{/name}","comments_url":"https://api.github.com/repos/masterzen/winrm/issues/35/comments","events_url":"https://api.github.com/repos/masterzen/winrm/issues/35/events","html_url":"https://github.com/masterzen/winrm/pull/35","id":113410049,"number":35,"title":"Fix race condition between command.Wait() and fetchOutput","user":{"login":"paulmey","id":1740197,"avatar_url":"https://avatars.githubusercontent.com/u/1740197?v=3","gravatar_id":"","url":"https://api.github.com/users/paulmey","html_url":"https://github.com/paulmey","followers_url":"https://api.github.com/users/paulmey/followers","following_url":"https://api.github.com/users/paulmey/following{/other_user}","gists_url":"https://api.github.com/users/paulmey/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmey/subscriptions","organizations_url":"https://api.github.com/users/paulmey/orgs","repos_url":"https://api.github.com/users/paulmey/repos","events_url":"https://api.github.com/users/paulmey/events{/privacy}","received_events_url":"https://api.github.com/users/paulmey/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-10-26T17:39:47Z","updated_at":"2015-10-27T17:44:02Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/masterzen/winrm/pulls/35","html_url":"https://github.com/masterzen/winrm/pull/35","diff_url":"https://github.com/masterzen/winrm/pull/35.diff","patch_url":"https://github.com/masterzen/winrm/pull/35.patch"},"body":"I've observed the exitcode sometimes coming back as 0 if it should have been non-zero. \r\nIt turns out that both command.Wait() and fetchOutput(* command) were racing to receive command.done. The break statements were only [breaking out of the select, not the for loop](https://golang.org/ref/spec#Break_statements), so the exit code kept being updated forever. \r\n\r\nApparently at least one implementation of WSMAN returns ExitCode 0 on subsequent Receive messages, even though it was non-zero on the first Receive response with `CommandState/@State=done`.\r\n\r\nI changed fetchOutput/Wait to the canonical 'done channel' pattern to terminate on the first encounter of a `CommandState/@State=done` fragment.\r\n\r\nNot sure why fetchOutput was trying to receive command.done, since it's only sent by the very same function?\r\n"},"comment":{"url":"https://api.github.com/repos/masterzen/winrm/issues/comments/151583548","html_url":"https://github.com/masterzen/winrm/pull/35#issuecomment-151583548","issue_url":"https://api.github.com/repos/masterzen/winrm/issues/35","id":151583548,"user":{"login":"paulmey","id":1740197,"avatar_url":"https://avatars.githubusercontent.com/u/1740197?v=3","gravatar_id":"","url":"https://api.github.com/users/paulmey","html_url":"https://github.com/paulmey","followers_url":"https://api.github.com/users/paulmey/followers","following_url":"https://api.github.com/users/paulmey/following{/other_user}","gists_url":"https://api.github.com/users/paulmey/gists{/gist_id}","starred_url":"https://api.github.com/users/paulmey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paulmey/subscriptions","organizations_url":"https://api.github.com/users/paulmey/orgs","repos_url":"https://api.github.com/users/paulmey/repos","events_url":"https://api.github.com/users/paulmey/events{/privacy}","received_events_url":"https://api.github.com/users/paulmey/received_events","type":"User","site_admin":false},"created_at":"2015-10-27T17:44:02Z","updated_at":"2015-10-27T17:44:02Z","body":"In the current code, fetchOutput never terminates, I believe. The break's only break out of the select clause, not the for loop. Even in this case, a command could get stuck, if the server never returns 'done' (ie. it's waiting for input in pending state)."}}