[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()}
Re: [bug-gawk] system() should return != 0 when the process is killed, Stephane Chazelas, 2016/03/05
Re: [bug-gawk] system() should return != 0 when the process is killed,
Aharon Robbins <=
Re: [bug-gawk] system() should return != 0 when the process is killed, Aharon Robbins, 2016/03/10