Why do high exit codes on Linux shells (>= 256) not work as expected?

Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
I discovered a strange behaviour (reproducible with zsh and bash on my system):
$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11
So after 256 it begins to count from 1 again. But why?
The bash man page does not indicate that there is a maximum number:
exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.
And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.
So why does this happen? And why is not it documented?
x64, Fedora 26
bash shell zsh exit exit-code
add a comment |Â
up vote
1
down vote
favorite
I discovered a strange behaviour (reproducible with zsh and bash on my system):
$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11
So after 256 it begins to count from 1 again. But why?
The bash man page does not indicate that there is a maximum number:
exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.
And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.
So why does this happen? And why is not it documented?
x64, Fedora 26
bash shell zsh exit exit-code
It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
â xhienne
Sep 26 '17 at 23:47
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I discovered a strange behaviour (reproducible with zsh and bash on my system):
$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11
So after 256 it begins to count from 1 again. But why?
The bash man page does not indicate that there is a maximum number:
exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.
And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.
So why does this happen? And why is not it documented?
x64, Fedora 26
bash shell zsh exit exit-code
I discovered a strange behaviour (reproducible with zsh and bash on my system):
$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11
So after 256 it begins to count from 1 again. But why?
The bash man page does not indicate that there is a maximum number:
exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.
And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.
So why does this happen? And why is not it documented?
x64, Fedora 26
bash shell zsh exit exit-code
bash shell zsh exit exit-code
asked Sep 26 '17 at 21:44
rugk
271319
271319
It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
â xhienne
Sep 26 '17 at 23:47
add a comment |Â
It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
â xhienne
Sep 26 '17 at 23:47
It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
â xhienne
Sep 26 '17 at 23:47
It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
â xhienne
Sep 26 '17 at 23:47
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
2
down vote
The POSIX manual page for the shell command exit(1p) states:
SYNOPSIS
exit [n]
DESCRIPTION
The
exitutility shall cause the shell to exit with the exit status specified by the unsigned decimal integern. Ifnis specified but its value is not between 0 and 255 inclusive, the exit status is undefined.
So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.
add a comment |Â
up vote
2
down vote
It is documented in the manual of the exit system function:
The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
Start] or any other value, though only the least significant 8 bits
(that is, status & 0377) shall be available to a waiting parent
process. [Option End]
Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.
1
Note thatwaitid()lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as$.sh.code
â Stéphane Chazelas
Sep 26 '17 at 22:07
Sorry$.sh.status, not$.sh.code(which is thesi_code)
â Stéphane Chazelas
Sep 26 '17 at 22:23
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I triedint main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status);and got1andDDwhich seems to indicate that indeed only the last 8 bits make it through.
â PSkocik
Sep 26 '17 at 22:26
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
The POSIX manual page for the shell command exit(1p) states:
SYNOPSIS
exit [n]
DESCRIPTION
The
exitutility shall cause the shell to exit with the exit status specified by the unsigned decimal integern. Ifnis specified but its value is not between 0 and 255 inclusive, the exit status is undefined.
So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.
add a comment |Â
up vote
2
down vote
The POSIX manual page for the shell command exit(1p) states:
SYNOPSIS
exit [n]
DESCRIPTION
The
exitutility shall cause the shell to exit with the exit status specified by the unsigned decimal integern. Ifnis specified but its value is not between 0 and 255 inclusive, the exit status is undefined.
So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.
add a comment |Â
up vote
2
down vote
up vote
2
down vote
The POSIX manual page for the shell command exit(1p) states:
SYNOPSIS
exit [n]
DESCRIPTION
The
exitutility shall cause the shell to exit with the exit status specified by the unsigned decimal integern. Ifnis specified but its value is not between 0 and 255 inclusive, the exit status is undefined.
So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.
The POSIX manual page for the shell command exit(1p) states:
SYNOPSIS
exit [n]
DESCRIPTION
The
exitutility shall cause the shell to exit with the exit status specified by the unsigned decimal integern. Ifnis specified but its value is not between 0 and 255 inclusive, the exit status is undefined.
So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.
edited Sep 26 '17 at 22:02
Kusalananda
106k14209327
106k14209327
answered Sep 26 '17 at 22:01
Fox
4,75111131
4,75111131
add a comment |Â
add a comment |Â
up vote
2
down vote
It is documented in the manual of the exit system function:
The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
Start] or any other value, though only the least significant 8 bits
(that is, status & 0377) shall be available to a waiting parent
process. [Option End]
Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.
1
Note thatwaitid()lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as$.sh.code
â Stéphane Chazelas
Sep 26 '17 at 22:07
Sorry$.sh.status, not$.sh.code(which is thesi_code)
â Stéphane Chazelas
Sep 26 '17 at 22:23
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I triedint main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status);and got1andDDwhich seems to indicate that indeed only the last 8 bits make it through.
â PSkocik
Sep 26 '17 at 22:26
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
add a comment |Â
up vote
2
down vote
It is documented in the manual of the exit system function:
The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
Start] or any other value, though only the least significant 8 bits
(that is, status & 0377) shall be available to a waiting parent
process. [Option End]
Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.
1
Note thatwaitid()lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as$.sh.code
â Stéphane Chazelas
Sep 26 '17 at 22:07
Sorry$.sh.status, not$.sh.code(which is thesi_code)
â Stéphane Chazelas
Sep 26 '17 at 22:23
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I triedint main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status);and got1andDDwhich seems to indicate that indeed only the last 8 bits make it through.
â PSkocik
Sep 26 '17 at 22:26
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
add a comment |Â
up vote
2
down vote
up vote
2
down vote
It is documented in the manual of the exit system function:
The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
Start] or any other value, though only the least significant 8 bits
(that is, status & 0377) shall be available to a waiting parent
process. [Option End]
Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.
It is documented in the manual of the exit system function:
The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
Start] or any other value, though only the least significant 8 bits
(that is, status & 0377) shall be available to a waiting parent
process. [Option End]
Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.
edited Sep 26 '17 at 22:35
answered Sep 26 '17 at 21:54
PSkocik
17.2k24589
17.2k24589
1
Note thatwaitid()lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as$.sh.code
â Stéphane Chazelas
Sep 26 '17 at 22:07
Sorry$.sh.status, not$.sh.code(which is thesi_code)
â Stéphane Chazelas
Sep 26 '17 at 22:23
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I triedint main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status);and got1andDDwhich seems to indicate that indeed only the last 8 bits make it through.
â PSkocik
Sep 26 '17 at 22:26
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
add a comment |Â
1
Note thatwaitid()lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as$.sh.code
â Stéphane Chazelas
Sep 26 '17 at 22:07
Sorry$.sh.status, not$.sh.code(which is thesi_code)
â Stéphane Chazelas
Sep 26 '17 at 22:23
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I triedint main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status);and got1andDDwhich seems to indicate that indeed only the last 8 bits make it through.
â PSkocik
Sep 26 '17 at 22:26
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
1
1
Note that
waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.codeâ Stéphane Chazelas
Sep 26 '17 at 22:07
Note that
waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.codeâ Stéphane Chazelas
Sep 26 '17 at 22:07
Sorry
$.sh.status, not $.sh.code (which is the si_code)â Stéphane Chazelas
Sep 26 '17 at 22:23
Sorry
$.sh.status, not $.sh.code (which is the si_code)â Stéphane Chazelas
Sep 26 '17 at 22:23
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried
int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.â PSkocik
Sep 26 '17 at 22:26
@StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried
int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.â PSkocik
Sep 26 '17 at 22:26
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
â Stéphane Chazelas
Sep 26 '17 at 22:30
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
@StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
â PSkocik
Sep 26 '17 at 22:33
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f394639%2fwhy-do-high-exit-codes-on-linux-shells-256-not-work-as-expected%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
â xhienne
Sep 26 '17 at 23:47