RFC: uniform exit codes

Elias Pipping pipping.elias at icloud.com
Fri Sep 2 14:53:01 UTC 2016


Dear list,

I’d like to talk about exit codes for a bit. The uiop/run-program::%wait-process-result function e.g. currently waits for a process to terminate and then returns something. An exit-code. What would you expect that to be? What would you like it to be?

(I’ve already had a long discussion about this with Robert but Faré asked me to take it to the mailing list, too).

An exit code should be a number and lie between 0 and 255, with only 0 signalling success, as far as I understand. A ‘return -1’ in C ends up as a 255 once I check for it in lisp or shell. Beyond that there are customs but not standards (there is sysexits.h but it’s not used all that much)

Please consider the three shell scripts that each contain just one line:

(1) exit 15
(2) kill $$
(3) sh -c ‘kill $$’

If you saved them in separate scripts and ran them from within a shell, the exit code would be 15/143/143. The take-away messages from that for me are that

- the shell uses 128+n if the process dies in response to signal n
- there are cases where the exit code is greater than 128 even though the process itself did not die in response to a signal, thereby interfering with this logic
- the shell cannot distinguish (2) and (3)

From within lisp, often but not always (2) and (3) can be distinguished. Sometimes, a process-wait function will return something like 15/(0 15)/(143 0) for the above examples(*); sometimes a process-status function will report (:exited 15)/(:signaled 15)/(:exited 143).

But some implementations will behave like the shell and always return 15/143/143, e.g. ABCL, LispWorks <7, and Allegro CL with :wait t.

So the thing that we can reliably do is produce the sequence 15/143/143. Please note that even this baseline is already a proposal for a change: With today’s UIOP master branch, you could also get things such as 15/15/143, 15/0/143, or 15/:sigterm/143, if I’m not mistaken.

What we could not reliably do is e.g. return things like 15/-15/143 or (15 :exited)/(15 :signaled)/(143 :exited). What I’ve implemented so far is a compromise. Some platforms might return 15/(143 15)/143 and others just 15/143/143. The (143 15) could easily be turned into (143 :signaled) instead, that’s a matter of taste, the take-away message remains, though, that you couldn’t be sure that what you think is case (2) isn’t really case (3). So that leaves also the option of “let’s just not bother with distinguishing the two”.

Looking forward to your feedback,


Elias

(*) I’m using (x y) as a short-hand for (values x y) here, rather than (list x y)


More information about the asdf-devel mailing list