Quelles sont les valeurs min et max des codes de sortie suivants sous Linux:
exit
).return
). Je pense que c'est entre 0
et 255
.Le numéro transmis à l'appel système _exit()
/exit_group()
(parfois appelé code de sortie pour éviter le ambiguïté avec l'état de sortie qui fait également référence à un codage du code de sortie ou du numéro de signal et des informations supplémentaires selon que le processus a été tué ou s'est terminé normalement ) est de type int
, donc sur les systèmes de type Unix comme Linux, généralement un entier 32 bits avec des valeurs de -2147483648 (-231) à 2147483647 (231-1).
Cependant, sur tous les systèmes, lorsque le processus parent (ou le sous-enfant ou init
si le parent est décédé) utilise la fonction wait()
, waitpid()
, wait3()
, wait4()
appels système pour le récupérer, seuls les 8 bits inférieurs sont disponibles (valeurs 0 à 255 (28-1)).
Lorsque vous utilisez l'API waitid()
(ou un gestionnaire de signaux sur SIGCHLD), sur la plupart des systèmes (et comme POSIX l'exige désormais plus clairement dans l'édition 2016 de la norme (voir _exit()
spécification )), le numéro complet est disponible (dans le champ si_status
de la structure retournée). Ce n'est pas encore le cas sur Linux, qui tronque également le nombre à 8 bits avec l'API waitid()
, bien que cela soit susceptible de changer à l'avenir.
En règle générale, vous ne souhaitez utiliser que les valeurs 0 (signifiant généralement succès) à 125 uniquement, car de nombreux shells utilisent des valeurs supérieures à 128 dans leur représentation $?
De l'état de sortie pour coder le numéro de signal d'un processus en cours de suppression et 126 et 127 pour des conditions spéciales.
Vous voudrez peut-être utiliser 126 à 255 sur exit()
pour signifier la même chose que pour le $?
Du shell (comme quand un script fait ret=$?; ...; exit "$ret"
). L'utilisation de valeurs en dehors de 0 -> 255 n'est généralement pas utile. Vous ne feriez généralement cela que si vous savez que le parent utilisera l'API waitid()
sur les systèmes qui ne tronquent pas et que vous avez besoin de la plage de valeurs 32 bits. Notez que si vous effectuez une exit(2048)
par exemple, cela sera vu comme un succès par les parents utilisant les API traditionnelles wait*()
.
Plus d'infos sur:
J'espère que cette Q&R devrait répondre à la plupart de vos autres questions et clarifier ce que l'on entend par état de sortie . J'ajouterai encore quelques choses:
Un processus ne peut se terminer que s'il est tué ou s'il appelle les appels système _exit()
/exit_group()
. Lorsque vous revenez de main()
dans C
, la libc appelle cet appel système avec la valeur de retour.
La plupart des langues ont une fonction exit()
qui encapsule cet appel système et la valeur qu'ils prennent, le cas échéant, est généralement transmise telle quelle à l'appel système. (notez que ceux-ci font généralement plus de choses comme le nettoyage effectué par la fonction exit()
de C qui vide les tampons stdio, exécute les hooks atexit()
...)
C'est le cas d'au moins:
$ strace -e exit_group awk 'BEGIN{exit(1234)}'
exit_group(1234) = ?
$ strace -e exit_group mawk 'BEGIN{exit(1234)}'
exit_group(1234) = ?
$ strace -e exit_group busybox awk 'BEGIN{exit(1234)}'
exit_group(1234) = ?
$ echo | strace -e exit_group sed 'Q1234'
exit_group(1234) = ?
$ strace -e exit_group Perl -e 'exit(1234)'
exit_group(1234) = ?
$ strace -e exit_group python -c 'exit(1234)'
exit_group(1234) = ?
$ strace -e exit_group expect -c 'exit 1234'
exit_group(1234) = ?
$ strace -e exit_group php -r 'exit(1234);'
exit_group(1234) = ?
$ strace -e exit_group zsh -c 'exit 1234'
exit_group(1234)
Vous voyez parfois certains qui se plaignent lorsque vous utilisez une valeur en dehors de 0-255:
$ echo 'm4exit(1234)' | strace -e exit_group m4
m4:stdin:1: exit status out of range: `1234'
exit_group(1) = ?
Certains obus se plaignent lorsque vous utilisez une valeur négative:
$ strace -e exit_group dash -c 'exit -1234'
dash: 1: exit: Illegal number: -1234
exit_group(2) = ?
$ strace -e exit_group yash -c 'exit -- -1234'
exit: `-1234' is not a valid integer
exit_group(2) = ?
POSIX laisse le comportement indéfini si la valeur passée à la commande spéciale exit
spéciale est en dehors de 0-> 255.
Certains shells présentent des comportements inattendus si vous le faites:
bash
(et mksh
mais pas pdksh
sur lequel il est basé) se charge de tronquer la valeur à 8 bits:
$ strace -e exit_group bash -c 'exit 1234'
exit_group(210) = ?
Donc, dans ces shells, si vous voulez quitter avec une valeur en dehors de 0-255, vous devez faire quelque chose comme:
exec zsh -c 'exit -- -12345'
exec Perl -e 'exit(-12345)'
C'est-à-dire exécuter une autre commande dans le même processus que peut appeler l'appel système avec la valeur souhaitée.
comme mentionné dans cet autre Q&R, ksh93
a le comportement le plus étrange pour les valeurs de sortie de 257 à 256 + max_signal_number où au lieu d'appeler exit_group()
, il se tue avec le signal correspondant¹.
$ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
zsh: suspended (signal) ksh -c 'exit "$((256 + $(kill -l STOP)))"'
et sinon tronque le nombre comme bash
/mksh
.
¹ Cela devrait toutefois changer dans la prochaine version. Maintenant que le développement de ksh93
A été repris comme un effort communautaire en dehors d'AT & T, ce comportement, bien qu'encouragé par POSIX, est en train d'être inversé
Le minimum est 0
, et cela est considéré comme la valeur de réussite. Tous les autres sont un échec. Le maximum est 255
aussi connu sous le nom -1
.
Ces règles s'appliquent aux scripts et autres exécutables, ainsi qu'aux fonctions Shell.
De plus grandes valeurs résultent en modulo 256.
Cela semble si simple, mais oh les malheurs.
Le langage C (et qui suit directement ou indirectement la plupart des autres langages) requiert que le retour de main
soit équivalent à l'appel de exit
avec le même argument que la valeur de retour. Il s'agit d'un entier (le type de retour est très clairement int
), donc en principe la plage serait INT_MIN
à INT_MAX
.
Cependant, POSIX déclare que seuls les 8 bits les plus bas passés à exit
seront mis à la disposition d'un processus parent en attente, littéralement comme s'il s'agissait de "status & 0xFF".
Donc, dans la pratique, le code de sortie est un entier (toujours signé) dont seuls les 8 bits les plus bas sont définis.
Le minimum sera donc -128, et le maximum 127. Attendez, ce n'est pas vrai. Ce sera de 0 à 255.
Mais hélas, bien sûr, cela ne peut pas être aussi simple . En pratique, Linux (ou plutôt bash) fait différemment . La plage valide de codes retour est comprise entre 0 et 255 (c'est-à-dire non signé).
Pour éviter les confusions, c'est probablement une bonne idée de simplement supposer que les codes de retour ne soient pas signés et de convertir tout ce que vous récupérez de wait
en non signé . De cette façon, il est cohérent avec ce que vous voyez dans un Shell. Étant donné que les bits les plus élevés (y compris le plus significatif) sont effacés, ce n'est même pas "faux" car, bien que techniquement signés, les valeurs réelles ne sont toujours pas signées (puisque le bit de signe n'est jamais défini).
Cela permet également d'éviter l'erreur courante de comparer un code de sortie à -1
, qui pour une raison étrange ne semble jamais apparaître même lorsqu'un programme se termine avec -1
(eh bien, devinez pourquoi!).
À propos de votre dernier point, en revenant d'une fonction, si cette fonction se trouve être main
, alors voir ci-dessus. Sinon, cela dépend du type de retour de la fonction, il pourrait en principe être n'importe quoi (y compris void
).
- Le code de sortie renvoyé par un exécutable binaire (par exemple: un programme C).
- Le code de sortie renvoyé par un script bash (lors de l'appel à exit).
Les codes de sortie de n'importe quel processus - qu'il s'agisse d'un exécutable binaire, d'un script Shell ou de toute autre chose - vont de 0 à 255. Il est possible de passer une valeur plus grande à exit()
, mais uniquement les 8 bits inférieurs du statut sont mis à la disposition d'autres processus via wait()
.
- Le code de sortie renvoyé par une fonction (lors de l'appel de retour). Je pense que c'est entre 0 et 255.
Une fonction C peut être déclarée comme retournant presque n'importe quel type. Les limites de sa valeur de retour sont entièrement déterminées par ce type: par exemple, -128 à 127 pour une fonction renvoyant signed char
, ou 0 à 4,2 milliards pour une fonction renvoyant unsigned int
, ou tout nombre à virgule flottante jusqu'à inf
inclus pour une fonction renvoyant double
. Et cela ne compte pas les types non numériques, comme void *
ou un struct
...