bug-gawk
[Top][All Lists]
Advanced

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

Re: [bug-gawk] system() should return != 0 when the process is killed


From: Aharon Robbins
Subject: Re: [bug-gawk] system() should return != 0 when the process is killed
Date: Mon, 07 Mar 2016 23:38:54 +0200
User-agent: Heirloom mailx 12.5 6/20/10

Hi. Re this:

> Date: Thu, 3 Mar 2016 17:58:25 +0100
> From: Tobia Conforto <address@hidden>
> To: address@hidden
> Subject: [bug-gawk] system() should return != 0 when the process is killed
>
> Hello
>
> It looks like gawk's system() only returns bits 8 to 15 (or s>>8) of the
> value returned by system(3), discarding any information about the
> termination of the child process by a signal.

This is what Brian Kernighan's awk does, which is likely why the
current code works this way.

> This breaks use cases like this (and probably others):
>
>     do {
>         ...
>     } while (! system("sleep 10"))
>
> where the intention is to break the loop when the user interrupts (^C) the
> child process.
>
> It would arguably be better if gawk returned a composite code, as
> traditionally done by most shells and interpreters, for example (s&127)+128
> if killed, s>>8 otherwise, as in Bash.
>
> Other awk implementations (nawk, bwk-awk, and mawk) always return values !=
> 0 when the child process executed by system() is killed by a signal.

Not true.  BWK awk returns some bizarre fraction. mawk exits. MKS awk
and Busybox awk return zero.

I propose the following patch, which should give you what you want.

Arnold
----------------------------------------------
diff --git a/NEWS b/NEWS
index 9386bae..31c8471 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,9 @@ Changes from 4.1.3 to 4.1.x
 7. The profiler / pretty-printer now chains else-if statements instead
    of causing cascading elses.
 
+8. The return value of system() has been enhanced to convey more information.
+   See the doc.
+
 Changes from 4.1.2 to 4.1.3
 ---------------------------
 
diff --git a/builtin.c b/builtin.c
index a62437a..375497f 100644
--- a/builtin.c
+++ b/builtin.c
@@ -2081,8 +2081,26 @@ do_system(int nargs)
 
                os_restore_mode(fileno(stdin));
                ret = system(cmd);
-               if (ret != -1)
-                       ret = WEXITSTATUS(ret);
+               /*
+                * 3/2016. What to do with ret? It's never simple.
+                * POSIX says to use the full return value. BWK awk
+                * uses just the exit status. That seems more useful to
+                * me, but then death by signal info gets lost.
+                * So we compromise as follows:
+                */
+               if (ret != -1) {
+                       if (do_posix)
+                               ;       /* leave it alone, full 16 bits */
+                       else if (WIFEXITED(ret))
+                               ret = WEXITSTATUS(ret); /* normal exit */
+                       else if (do_traditional)
+                               ret = 0;        /* ignore signal death */
+                       else if (WIFSIGNALED(ret))
+                               /* use 256 since exit values are 8 bits */
+                               ret = WTERMSIG(ret) + 256;
+                       else
+                               ret = 0;        /* shouldn't get here */
+               }
                if ((BINMODE & BINMODE_INPUT) != 0)
                        os_setbinmode(fileno(stdin), O_BINARY);
 
diff --git a/doc/gawk.1 b/doc/gawk.1
index da1f583..ca51a53 100644
--- a/doc/gawk.1
+++ b/doc/gawk.1
@@ -13,7 +13,7 @@
 .              if \w'\(rq' .ds rq "\(rq
 .      \}
 .\}
-.TH GAWK 1 "Dec 17 2015" "Free Software Foundation" "Utility Commands"
+.TH GAWK 1 "Mar 7 2016" "Free Software Foundation" "Utility Commands"
 .SH NAME
 gawk \- pattern scanning and processing language
 .SH SYNOPSIS
@@ -2259,6 +2259,7 @@ Execute the command
 .IR cmd-line ,
 and return the exit status.
 (This may not be available on non-\*(PX systems.)
+See the manual for the full details on the exit status.
 .TP
 \&\fBfflush(\fR[\fIfile\^\fR]\fB)\fR
 Flush any buffers associated with the open output file or pipe
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index ff5672a..4b0af55 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -17530,7 +17530,7 @@ it is all buffered and sent down the pipe to 
@command{cat} in one shot.
 @cindex interacting with other programs
 Execute the operating system
 command @var{command} and then return to the @command{awk} program.
-Return @var{command}'s exit status.
+Return @var{command}'s exit status (see further on).
 
 For example, if the following fragment of code is put in your @command{awk}
 program:
@@ -17569,6 +17569,29 @@ When @option{--sandbox} is specified, the 
@code{system()} function is disabled
 (@pxref{Options}).
 @end quotation
 
+On POSIX systems, a command's exit status is a 16-bit number. The exit
+value passed to the C @code{exit()} function is held in the high-order
+eight bits. The low-order bits indicate if the process was killed by a
+signal (bit 7) and if so, the signal number (bits 0--6).
+
+Traditionally, @command{awk}'s @code{system()} function has simply
+returned the exit status value and ignored death-by-signal. POSIX
+states that @command{awk}'s @code{system()} should return the full
+16-bit value.
+
address@hidden steers a middle ground. With @option{--posix}, it returns
+the full 16-bit value. By default, it returns just the exit status. The
address@hidden option forces @command{gawk} to ignore
+death-by-signal, in which case @code{system()} returns zero.
+
+If the process was killed by a signal, @command{gawk}'s @code{system()}
+returns 256 + @var{sig}, where @var{sig} is the number of the signal
+that killed the process.  Since exit values are eight bits, where the
+values range from 0--255, using 256 + @var{sig} lets you clearly distinguish
+normal exit from death-by-signal.
+
+If some kind of error occurred, @code{system()} returns @minus{}1.
+
 @end table
 
 @sidebar Controlling Output Buffering with @code{system()}



reply via email to

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