Skip to content

[UNIX] Enrich Process.wait() return value with exit code enums #2794

Description

@giampaolo

Current behavior

Process.wait() currently returns an IntEnum when a process is killed by a signal (42368e6). Negative exit codes are converted to a negative enum (e.g. <NegSignal.SIGTERM: -15>):

>>> import psutil
>>> p = psutil.Process(9891)
>>> p.terminate()
>>> p.wait()
<NegSignal.SIGTERM: -15>

For non-negative exit codes, a plain int is returned.

>>> p.wait()
0

Proposal

Extend the same enum treatment to non-negative exit codes, so that p.wait() returns something like <Exitcode.EX_OK: 0> instead of a bare 0.

>>> p.wait()
<ExitCode.EX_OK: 0>

Which exit codes to include

There are three candidate sets of exit codes to consider.

  1. EX_OK (0): always mean "success" on every platform. The safest to include since it's unambiguous (including on Windows).

  2. EX_USAGE, EX_NOPERM, etc., from sysexits.h header file, see https://man7.org/linux/man-pages/man3/sysexits.h.3head.html. These are "semi-standard" codes, even though rarely used. Man page says they were added by sendmail(8) program. Probably the "high" range 64-78 was chosen to avoid collisions with common application-defined exit codes (1, 2, 3...).

    • Argument pro: a program that returns a value in this range arguably made a conscious decision to use that specific number, hence to avoid to this "semi-convention". E.g. EX_NOPERM (permission denied) is a useful code to return for a program.

    • Argument against: a program with many error paths using incrementing exit codes could land in the 64-78 range by accident, without even knowing about sysexits.h. Uncommon in practice, but possible.

  3. Shell conventions (126, 127, 128). Shells assign specific meanings to certain exit codes: 126 means "command cannot execute" (permission denied), 127 means "command not found", 128 means "invalid argument to exit". See https://stackoverflow.com/questions/1101957/are-there-any-standard-exit-status-codes-in-linux.

    • Argument pro: These are well known shell conventions. In practice, many processes tracked by psutil are commands lauched by shell, and users of p.wait() will recognize these codes. Seeing <Exitcode.EX_COMMAND_NOT_FOUND: 127> would be helpful more often than misleading.

    • Argument against: these codes are assigned by the shell, not by the program. When psutil calls waitpid() and gets 127, it means the process called exit(127), which could be a Python script doing sys.exit(127). psutil cannot determine whether the process was launched via a shell or not, so it cannot know whether the shell
      convention applies-

  4. Exit codes 1-63. These are all user-defined codes, so they should not be included.

Windows considerations

I made some research, and on Windows this seems even less standardized than on POSIX, so this would be a UNIX-only feature. But still, on Windows we could return EX_OK (0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    new-apithe public API grows: a new function, argument, or returned valueunixplatform : shared POSIX code, when no single OS fits

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions