-
Notifications
You must be signed in to change notification settings - Fork 896
fix(pty): close output writer before reader on Windows to unblock close #8299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
cd01574
to
7972246
Compare
7972246
to
5770111
Compare
08cacc8
to
690a929
Compare
690a929
to
2bd817d
Compare
pty/pty_windows.go
Outdated
ret, _, err := procClosePseudoConsole.Call(uintptr(p.console)) | ||
if ret < 0 { | ||
return xerrors.Errorf("close pseudo console: %w", err) | ||
if ret := windows.Handle(ret); ret != windows.S_OK && ret != windows.S_FALSE { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review: I contemplated ignoring ret/err here entirely, however, in my testing it seems this function usually returns S_FALSE
(1). Since I can't find documentation for this behavior, we allow S_OK
too. Given positive error values, limiting this to negative doesn't make sense to me: https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Values like 0x80004001
are negative when interpreted as a signed 32 bit integer because they are encoded in two's compliment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
S_FALSE is a "success" code, so I think it's still fine to check ret<0 for in general.
In this specific case, Windows docs say that there is no return value, so my guess is that the Windows syscall libraries, or perhaps the Windows kernel itself is writing S_FALSE for this procedure to indicate that it's not an explicit "OK" because the call has no return value.
We could just drop the whole error handling block here and cite the docs that say this procedure doesn't return any values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Values like 0x80004001 are negative when interpreted as a signed 32 bit integer because they are encoded in two's compliment
True, however the return value from Call
is an uintptr and this ret
wasn't being cast to 32-bit. As such the ret < 0
was nonsensical. I don't know enough about Windows syscall internals to know if we can always cast it, that would assume a syscall always returns HRESULT (maybe it does).
In this specific case, Windows docs say that there is no return value, so my guess is that the Windows syscall libraries, or perhaps the Windows kernel itself is writing S_FALSE for this procedure to indicate that it's not an explicit "OK" because the call has no return value.
Sounds plausible, this value is at least not coming from Go and Windows does define success as a positive 32-bit integer.
We could just drop the whole error handling block here and cite the docs that say this procedure doesn't return any values.
I would still like to keep it, just in case. Unless we can confirm that this syscall can't fail in some way or form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed this to int32(ret) < 0
now, to be more generic and self-documenting via a new func winerrorFailed(r1 uintptr) bool
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do appreciate extra comments describing the Windows behavior, as I'm not a Windows developer 👍
I left a few comments on the wording in the comments.
pty/pty_windows.go
Outdated
ret, _, err := procClosePseudoConsole.Call(uintptr(p.console)) | ||
if ret < 0 { | ||
return xerrors.Errorf("close pseudo console: %w", err) | ||
if ret := windows.Handle(ret); ret != windows.S_OK && ret != windows.S_FALSE { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Values like 0x80004001
are negative when interpreted as a signed 32 bit integer because they are encoded in two's compliment
pty/pty_windows.go
Outdated
ret, _, err := procClosePseudoConsole.Call(uintptr(p.console)) | ||
if ret < 0 { | ||
return xerrors.Errorf("close pseudo console: %w", err) | ||
if ret := windows.Handle(ret); ret != windows.S_OK && ret != windows.S_FALSE { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
S_FALSE is a "success" code, so I think it's still fine to check ret<0 for in general.
In this specific case, Windows docs say that there is no return value, so my guess is that the Windows syscall libraries, or perhaps the Windows kernel itself is writing S_FALSE for this procedure to indicate that it's not an explicit "OK" because the call has no return value.
We could just drop the whole error handling block here and cite the docs that say this procedure doesn't return any values.
110f5e2
to
3762cb8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I haven't reproduced the issue on Windows, but I'm hoping this is a fix for the following issue (stuck on calling Close):
https://github.com/coder/coder/actions/runs/5442614267/jobs/9898091930?pr=8280