-
-
Notifications
You must be signed in to change notification settings - Fork 84
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
Abstract redirects and pipes into inputStream and outputStream interface #206
Conversation
Thanks for this -- this is excellent work! I hope to take a closer look at the code changes this weekend, but at first glance is looks like a good approach. FYI, I've just merged #207 to update to Go 1.16 so we can use |
That's great thanks! Do you mind if I rebase instead of merge? I rebase a lot it makes the commit history cleaner but spams up the issues & PRs... 😞 I noticed that the Linux test had a failure. It seemed that the signal may have been handled and the sh process itself did not exit due to signal. I'll have to dig in more there and research which sh implementation is used and how it handles signals, etc. Ofc that is just a guess for now. |
@juster Yep, rebasing is fine. My development style is usually "push any old commit to the PR branch, then squash and merge when merging the PR", but if you keep a clean commit history in the PR, I'm happy to apply directly to master instead. |
I found the problem with the
This test is running the
On my old Macbook This is an unfortunate design choice! Because now there is no way to be sure what the exit value of Oh well. As we've seen in #205 signal exits are kind of an overlooked gray area. I think I will try to avoid spawning a shell at all for this test and just run In my testing I also found some signals are caught by default with shells. For example, I will avoid
|
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 haven't reviewed iostream.go
or iostream_test.go
yet (the bulk of the PR!), but here's a few early comments I had time for yesterday. I'll try to get to the rest over the weekend.
Thanks again for this. Note that I'm fairly thorough in my reviews as I like to get quality code merged and code that I can "own" from here on out. Hopefully we'll end up with something we're both proud of!
Not a problem and no rush. I think I want to [edit: squash] the "cleanup" commit into the first commit and pretend it was always cleaned up. BTW, I found a simple way around the bash problem. I just need to use |
fc5297b
to
7f1c845
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.
Thanks @juster! I've done a thorough review now and left a lot of comments. They're mostly fairly minor refactoring requests, but the one major thing is I'd like to restructure the tests to be black-box tests that test external behaviour like the other interp
tests, rather than testing implementation details. I'm happy to discuss further if that's not possible.
One other thing: it looks like there's also merge/rebase conflicts from the |
258b10b
to
143937b
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.
Excellent, thanks! Just a few very minor change requests now.
Creates the iostream.go file and uses I/O stream interfaces for all file redirects and command pipes. Defines inputStream and outputStream interfaces which satisfy the io.ReadCloser and io.WriteCloser interfaces, respectively. Adds an additional .ExitCode() accessor to return the exit code for goawk's close() builtin function. When the argument to close() is a pipe, this mimicks gawk's behavior: 1. The value passed to exit() when process exits normally 2. 256 + signal code when process exits due to signal 3. 512 + signal code when process exits due to signal with a core dump Fixes benhoyt#203 Fixes benhoyt#204
Old behavior always returned -1 on a signal exit. Fixes benhoyt#205
Enable gawk tests "status-close" and "sigpipe1". "sigpipe1" is skipped on Windows because it relies on the SIGPIPE POSIX signal. Modify TestShellCommand to check interpreter exit after missing shell Adds some interpTests entries to check signal exit from system(). Also adds entries to check signal exit and normal exit from a piped command close().
25de3c6
to
07e8760
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.
Thanks for the updates and the little flags parser! Just one more change requested (and a couple of nits): I was intending that !windows
mean "skip on windows, regardless of interpreter" as I think that makes the most sense (and fits with the meaning of Go's own !windows
build constraint).
There is not much to test. The only important one I could think of was consistent behavior in the event of a double-close.
The !windows flag will cause both the external awk tests and the goawk tests to be skipped if the tests are running on Windows. Signal-based test cases were failing on windows for goawk because Windows does not support POSIX signals. These are simulated on cygwin which is what MSYS2 appears to be using. MSYS2 is preinstalled on the Windows image which the CI runs. My best guess is that the MSYS2 kill command is forcing the child process to terminate with (signal << 8) as the exit status. Additionally, the gawk in the Windows CI image is using cmd.exe and not sh. Naturally, there are no exec or kill commands available from cmd.exe. Ironically, the signal exit status behaves predictibly for gawk on cygwin. Stricter flag parsing exposed some interpTest entries that were missing a comment char ('#').
07e8760
to
90259cf
Compare
Thanks for your efforts here -- merged! I intend to address a couple of other issues and then release a new GoAWK version that includes this change. |
Sweet thanks! I noticed this failed test: https://github.com/benhoyt/goawk/actions/runs/6293036690/job/17083040381 It looks like there is a race and the shell exited before goawk could write to the pipe. I should probably change |
Sounds good -- please put up another PR with the fix. For the record, I can get it to fail a few times locally by running it 1000 times:
|
This creates the
inputStream
andoutputStream
interfaces which are satisfied by structs for all combinations of file/pipe and input/output:struct inFileStream
struct inCmdStream
struct outFileStream
struct outCmdStream
The streams satisfy the
io.ReadCloser
andio.WriteCloser
interfaces while theoutputStream
also has aFlush() error
method. Both types of streams also have anExitCode() int
method which makes it trivial to determine the result of aclose()
on those streams.This PR homogenizes behavior and fixes a number of minor issues related to command pipes. Gawk behavior is mimicked for the following:
close()
when closing a pipe. Exit due to signal is256 + signal
and if both a signal and coredump occurred it is512 + signal
. (see close() on pipe command does not return exit status #203)system()
builtin function. (see system() always returns -1 if process exits due to signal #205)A separate bug was fixed so that the child process information is cleaned up when
close()
is called on an input pipe (i.e. viagetline
). (see #204)