> From: Mark H Weaver <m...@netris.org> > Cc: l...@gnu.org, guile-devel@gnu.org > Date: Fri, 28 Feb 2014 05:20:11 -0500 > > >> > # define WIFEXITED(stat_val) (((stat_val) & 0xC0000000) == 0) > >> > # define WIFSIGNALED(stat_val) (((stat_val) & 0xC0000000) != 0) > >> > >> WIFSIGNALED(x) returns true if either of two high bits are 1. This > >> seems a bit too loose to me. > > > > Strictly speaking, any of these two bits or both of them could be set, > [...] > > In general, a > > program launched by Guile could have a debugger attached, and then it > > could potentially get an exception like 0x40010005 (Ctrl-C was pressed > > into a debugged program). > > Okay, in that case perhaps the definitions above are the best ones. > I'll leave it to your best judgment what definitions are most likely to > be "future proof", i.e. to correctly distinguish normal exits from > abnormal termination in future versions of Windows.
I think I will go with enforcing 0xC, since the other possible bit patterns are only supposed to be exposed to debuggers. > >> IMO, it would be reasonable to just return SIGTERM in all cases, like > >> Gnulib does, but perhaps we should map some known values to specific > >> signals. You mentioned that the equivalent of SIGSEGV on Windows > >> results in a 0xC0000005 status code. Any others worth mapping? > > > > Are you still talking about a program that crashed, or are you talking > > about a program that Guile forcibly killed? > > I think we should try to consider both of these cases, and also a third > case: programs that are forcibly killed by something other than Guile. The last case will look to us as a program that exited. I don't think we can know that it was killed, on Windows. > > My reasoning for not producing SIGTERM > > unconditionally was that it might be confusing for a Guile program > > that requested termination via some signal other than SIGTERM to see > > that the program was terminated by SIGTERM. I wanted WTERMSIG to > > return the same signal that was used to kill the program. > > I suspect that this is relatively unimportant. Perhaps so, but it's easy to produce the same signal, so I think it's worthwhile. We could use the values mapped from the Posix signals, if you like that better. > I suspect that it's more important to do our best to follow the > status code conventions used on Windows, because: > > * When Guile kills a process, the status code of the killed process > should make sense to its parent, even if that parent is not Guile. The only conventions I know of are those codes that start with 0xC. Not many programs interpret these special codes, but those which do will be able to make sense of them. > * When a Guile subprocess is killed by something other than Guile, > The Guile program should be able to make sense of the status code. As I write above, I don't think this goal is achievable on Windows. > > 0xC0000005 (access to invalid address) SIGSEGV > > 0xC0000008 (invalid handle) SIGSEGV > > 0xC000001D (illegal instruction) SIGILL > > 0xC0000025 (non-continuable exception) SIGILL > > 0xC000008C (array bounds exceeded) SIGSEGV > > 0xC000008D (float denormal) SIGFPE > > 0xC000008E (float divide by zero) SIGFPE > > 0xC000008F (float inexact) SIGFPE > > 0xC0000090 (float invalid operation) SIGFPE > > 0xC0000091 (float overflow) SIGFPE > > 0xC0000092 (float stack check) SIGFPE > > 0xC0000093 (float underflow) SIGFPE > > 0xC0000094 (integer divide by zero) SIGFPE > > 0xC0000095 (integer overflow) SIGFPE > > 0xC0000096 (privileged instruction) SIGILL > > 0xC00000FD (stack overflow) SIGSEGV > > 0xC000013A (Ctrl-C exit) SIGINT > > This looks good to me. OK, I will rewrite WTERMSIG and scm_kill to use this mapping. > We'll also have to decide what WTERMSIG should return by default, > when the status code is none of the values above. I don't see how we can return anything but zero, because we cannot know what was the signal then, or indeed whether the program was terminated by a signal. > Also, what if the top bits are something other than 0xCxxx? Should we > mask those off before looking up the code in the table above? I'm not sure I follow: when a program terminates due to fatal exception, it _always_ returns one of these codes (there are a few others, but they don't map to Posix signals, so I left them out). Therefore I think we should compare the exit code literally to these values. > I nearly imported the 'pipe-posix' Gnulib module as well, but I noticed > that they implemented it differently than you did. You wrote: > > > # define pipe(f) _pipe(f, 0, O_NOINHERIT) > > Whereas they do: _pipe(f, 4096, _O_BINARY). > > Can you help me understand the pros and cons to these two approaches? > One thing: I'm fairly sure that we'll want _O_BINARY, and I think we > should also make sure that the pipe buffer is no less than 4096 bytes. First, the binary and the no-inherit flags can be ORed, they are not mutually exclusive. I used the no-inherit flag because otherwise the descriptors will be inherited by the subprocesses. It seemed to me that preventing their inheritance is a better way. It's not really important in open-process, because the code I wrote duplicates the handles (which on Windows strips the no-inheritance bit). But it might be important in uses of scm_pipe. I think you are in a better position to judge whether the descriptors should be inherited or not. (Is there a way in Guile to make a descriptor non-inheritable after it was created?) As for using O_BINARY, I think using it is wrong in Guile: most programs that will communicate with us via pipes will use text-mode I/O on Windows, so reading their output in binary mode would mean we get CRLF end-of-lines verbatim, and Guile programs that do this will need special code to get rid of the CR characters. Can Guile code control this aspect of pipe I/O after the pipe was created? As for the 4096 value, zero is documented as meaning "use the default", but I couldn't find anywhere what that means. So I preferred an explicit value. Why do you think 4K might be insufficient?