[Top][All Lists]

[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 13:26:05 +0200

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

> 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?

reply via email to

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