guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Implement open-process and related functions on MinGW


From: Eli Zaretskii
Subject: Re: [PATCH] Implement open-process and related functions on MinGW
Date: Fri, 28 Feb 2014 11:10:25 +0200

> From: Mark H Weaver <address@hidden>
> Cc: address@hidden,  address@hidden
> 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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]