Discussion:
Special parameter ?
e***@gsyc.urjc.es
2018-09-21 11:23:57 UTC
Permalink
The man page of bash (Special Parameters section) says:

? expands to the exit status of the most
recently executed foreground pipeline.

Nevertheless, background commands also modify the
value of this variable.

Example:

***@omac:~$ false
***@omac:~$ sleep 2 &
(wait 3 seconds)
***@omac:~$ echo $?
0
***@omac:~$

In this example, the most recently executed foreground
command is false, so the value of $? should be 1.

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../. -I.././include -I.././lib -Wdate-time -D_FORTIFY_SOURCE=2 -g -O2 -fdebug-prefix-map=/build/bash-vEMnMR/bash-4.4.18=. -fstack-protector-strong -Wformat -Werror=format-security -Wall -Wno-parentheses -Wno-format-security
uname output: Linux omac 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.4
Patch Level: 19
Release Status: release

Description:
[Detailed description of the problem, suggestion, or complaint.]

Repeat-By:
[Describe the sequence of events that causes the problem
to occur.]

Fix:
[Description of how to fix the problem. If you don't know a
fix for the problem, don't include this section.]
Greg Wooledge
2018-09-21 12:57:05 UTC
Permalink
Post by e***@gsyc.urjc.es
? expands to the exit status of the most
recently executed foreground pipeline.
Nevertheless, background commands also modify the
value of this variable.
This is incorrect. The exit status of a background command can only
be retrieved by calling "wait" (or if the background command itself
chooses to write the forthcoming exit status to stdout, or to a file,
etc.).
Post by e***@gsyc.urjc.es
(wait 3 seconds)
0
In this example, the most recently executed foreground
command is false, so the value of $? should be 1.
Under "Lists":

If a command is terminated by the control operator &, the shell exe‐
cutes the command in the background in a subshell. The shell does not
wait for the command to finish, and the return status is 0.

You're seeing the status from the creation of the background job (which is
always 0), not from its completion.

Compare:

wooledg:~$ (sleep 3; exit 47) & pid=$!
[1] 19112
wooledg:~$ echo $?
0
wooledg:~$
[1]+ Exit 47 ( sleep 3; exit 47 )
wooledg:~$ echo $?
0
wooledg:~$ wait $pid; echo $?
47

Even after the background job completes, its exit status is never
propagated into the foreground shell's $? parameter. The only way
to retrieve the status is with a wait command which is given a PID or
a job specifier.
Enrique Soriano
2018-09-21 14:17:11 UTC
Permalink
Post by Greg Wooledge
You're seeing the status from the creation of the background job (which is
always 0), not from its completion.
Ah, I see.

Anyway, the behavior is not coherent with the manual page: in this
case, $? has the status from the creation of the background job,
that's not "the status of the most recently executed foreground
pipeline".

Regards
Eduardo A. Bustamante López
2018-09-21 15:17:33 UTC
Permalink
Post by Enrique Soriano
Post by Greg Wooledge
You're seeing the status from the creation of the background job (which is
always 0), not from its completion.
Ah, I see.
Anyway, the behavior is not coherent with the manual page: in this
case, $? has the status from the creation of the background job,
that's not "the status of the most recently executed foreground
pipeline".
The thing that creates the background job IS a foreground pipeline. It's a foreground pipeline that creates a background
job, if that makes sense.

***@ubuntu:~$ cat t.sh
(exit 2)
(exit 3) & pid=$!
echo $?
wait "$pid"
echo $?

***@ubuntu:~$ bash t.sh
0
3

I recommend to store the value of $? in a variable if you plan on using it afterwards, since it's extremely easy to end
up overriding its value.
Chet Ramey
2018-09-21 15:46:48 UTC
Permalink
Post by Eduardo A. Bustamante López
Post by Enrique Soriano
Post by Greg Wooledge
You're seeing the status from the creation of the background job (which is
always 0), not from its completion.
Ah, I see.
Anyway, the behavior is not coherent with the manual page: in this
case, $? has the status from the creation of the background job,
that's not "the status of the most recently executed foreground
pipeline".
The thing that creates the background job IS a foreground pipeline. It's a foreground pipeline that creates a background
job, if that makes sense.
You're right, but it might be less confusing if I removed the "foreground"
from the description.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ***@case.edu http://tiswww.cwru.edu/~chet/
Enrique Soriano
2018-09-21 16:05:39 UTC
Permalink
Post by Eduardo A. Bustamante López
The thing that creates the background job IS a foreground pipeline. It's a foreground pipeline that creates a background
job, if that makes sense.
Sure. That's the mechanism to implement the background job.

The problem is that the user that reads the manual is dealing with the
"background" and "foreground" abstractions; for him, the most recently
foreground command in my example is false.
Post by Eduardo A. Bustamante López
I recommend to store the value of $? in a variable if you plan on using it afterwards, since it's extremely easy to end
up overriding its value.
Thanks, but I am not trying to implement anything. I am trying to fix
the man page :)
Post by Eduardo A. Bustamante López
You're right, but it might be less confusing if I removed the "foreground"
from the description.
This could help.
--
Enrique Soriano
Escuela Superior de Ingeniería de Telecomunicación,
Universidad Rey Juan Carlos.
Tel: 914888762
http://gsyc.urjc.es/~esoriano
Continue reading on narkive:
Loading...