> From: Mark H Weaver <m...@netris.org> > Cc: l...@gnu.org, guile-devel@gnu.org > Date: Fri, 28 Feb 2014 02:22:19 -0500 > > However, I don't want to use the "0xC0000200 + SIGNAL" convention > "between Guile and itself" that you've invented. Instead, based on what > you wrote, I guess that we should make WIFSIGNALED(x) return true for > any status code of the form 0xC0000xxx, or maybe some larger set. I > guess that WIFEXITED(x) should return the logical not of WIFSIGNALED(x). > WIFSTOPPED(x) presumably should always return false. > > In the code you wrote: > > > # 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, although an exit code due to a fatal exception normally has both of them set. The individual bits are used by exceptions related to debugging a program, like the equivalent of SIGTRAP. 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). But I don't think these statuses will ever be propagated back to Guile as a parent process, they are only sent to the attached debugger, which must handle them. With this in mind, do you like the below variant of WIFSIGNALED better? #define WIFSIGNALED(stat_val) (((stat_val) & 0xC0000000) == 0xC0000000) All of the fatal exceptions that are of interest exit with a status that has these two bits set. As for the lower bits, I didn't see anywhere documentation of which ones can or cannot be set, and newer versions of Windows enlarge the maximum value there, although the interesting values I do see have non-zero bits only in the lower 12 bits. So if you prefer something like this: #define WIFSIGNALED(stat_val) \ (((stat_val) & 0xC0000000) == 0xC0000000 && ((stat_val) & 0xFFF) != 0) then we could go with that as well. I would actually prefer not to test those lower bits, since we don't really know which values there are legitimate, and OTOH the chance that an application deliberately chooses to exit with any of these large values for any purpose other than reporting a fatal exception are slim at best. > > # define WTERMSIG(stat_val) ((stat_val > 0xC0000200) ? stat_val - > > 0xC0000200 : stat_val) > > I'd prefer to define WTERMSIG differently that this, which would return > very large values like 0xC0000005 for the Windows equivalent of SIGSEGV. > I think we should try to translate these until something that will make > more sense to a program written for POSIX. > > 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? SIGTERM only makes sense in the latter case. 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. Since terminating a program on Windows provides an opportunity to specify the exit code, we might as well use that opportunity to our advantage in this case. As for mapping these values to Posix signals: yes, this is possible. Here's the suggested mapping of values I consider useful: 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 (The 0xC0000200+signo trick was just a simple way around a proper mapping, and also a way to keep out of the OS codes. Also, that code was originally written years ago, when I don't think I knew all of the above.) You will see that there's no mapping for SIGTERM here. If having that is important, we could map the last one to SIGTERM, since a program is frequently forcibly terminated on Windows by simulating a Ctrl-C keypress to it. (As for SIGKILL, Windows doesn't have its definition in its headers, AFAIK.) > I will respond to the other subthreads at a later date. Thanks.