ExitCodes 大于 255,可能吗? [英] ExitCodes bigger than 255, possible?

查看:32
本文介绍了ExitCodes 大于 255,可能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果是,在哪个操作系统、shell 或其他什么操作系统上?

If yes, on which operating system, shell or whatever?

考虑下面的java程序(我使用java作为例子,任何语言都适合这个问题,更多的是关于操作系统):

Consider the following java program (I'm using java just as an example, any language would be good for this question, which is more about operation systems):

public class ExitCode {
    public static void main(String args[]) {
        System.exit(Integer.parseInt(args[0]));
    }
}

在 Linux 和 bash 上运行它,它返回的值总是小于等于 255,例如(echo $? 打印上一条执行命令的退出码)

Running it on Linux and bash, it returns always values less equal 255, e.g. (echo $? prints the exit code of the previous executed command)

> java ExitCode 2; echo $?
2

> java ExitCode 128; echo $?
128

> java ExitCode 255; echo $?
255

> java ExitCode 256; echo $?
0

> java ExitCode 65536; echo $?
0

<小时>

已下面的(迄今为止唯一的)答案充分解释了 UNIX 上发生的情况.我仍然想知道其他操作系统.


EDITED: the (only, so far) answer below fully explain what happens on UNIXes. I'm still wondering about other OSes.

推荐答案

Using wait() or waitpid()

在使用 POSIX 函数的 Unix 和衍生产品上是不可能的,例如 wait()waitpid().返回的退出状态信息由两个 8 位字段组成,一个包含退出状态,另一个包含有关死因的信息(0 表示在程序控制下有序退出,其他值表示信号杀死它,并表示是否一个核心被转储了).

Using wait() or waitpid()

It is not possible on Unix and derivatives using POSIX functions like wait() and waitpid(). The exit status information returned consists of two 8-bit fields, one containing the exit status, and the other containing information about the cause of death (0 implying orderly exit under program control, other values indicating that a signal killed it, and indicating whether a core was dumped).

如果你努力工作,并阅读sigaction的POSIX规范()信号操作,你会发现你可以拿到子进程传递给exit()的32位值.然而,这并不完全是直截了当的.

If you work hard, and read the POSIX specification of sigaction() and <signal.h> and Signal Actions, you will find that you can get hold of the 32-bit value passed to exit() by a child process. However, it is not completely straight-forward.

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

static siginfo_t sig_info = { 0 };
static volatile sig_atomic_t sig_num = 0;
static void *sig_ctxt = 0;

static void catcher(int signum, siginfo_t *info, void *vp)
{
    sig_num = signum;
    sig_info = *info;
    sig_ctxt = vp;
}

static void set_handler(int signum)
{
    struct sigaction sa;
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = catcher;
    sigemptyset(&sa.sa_mask);

    if (sigaction(signum, &sa, 0) != 0)
    {
        int errnum = errno;
        fprintf(stderr, "Failed to set signal handler (%d: %s)
", errnum, strerror(errnum));
        exit(1);
    }
}

static void prt_interrupt(FILE *fp)
{
    if (sig_num != 0)
    {
        fprintf(fp, "Signal %d from PID %d (status 0x%.8X; UID %d)
",
                sig_info.si_signo, (int)sig_info.si_pid, sig_info.si_status,
                (int)sig_info.si_uid);
        sig_num = 0;
    }
}

static void five_kids(void)
{
    const int base = 0xCC00FF40;
    for (int i = 0; i < 5; i++)
    {
        pid_t pid = fork();
        if (pid < 0)
            break;
        else if (pid == 0)
        {
            printf("PID %d - exiting with status %d (0x%.8X)
",
                   (int)getpid(), base + i, base + i);
            exit(base + i);
        }
        else
        {
            int status = 0;
            pid_t corpse = wait(&status);
            if (corpse != -1)
                printf("Child: %d; Corpse: %d; Status = 0x%.4X - waited
", pid, corpse, (status & 0xFFFF));
            struct timespec nap = { .tv_sec = 0, .tv_nsec = 1000000 }; // 1 millisecond
            nanosleep(&nap, 0);
            prt_interrupt(stdout);
            fflush(0);
        }
    }
}

int main(void)
{
    set_handler(SIGCHLD);
    five_kids();
}

运行时(从 sigexit73.c 编译的程序 sigexit73),这会产生如下输出:

When run (program sigexit73 compiled from sigexit73.c), this produces output like:

$ sigexit73
PID 26599 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26599 (status 0xCC00FF40; UID 501)
Child: 26600; Corpse: 26599; Status = 0x4000 - waited
PID 26600 - exiting with status -872349887 (0xCC00FF41)
Signal 20 from PID 26600 (status 0xCC00FF41; UID 501)
Child: 26601; Corpse: 26600; Status = 0x4100 - waited
PID 26601 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26601 (status 0xCC00FF42; UID 501)
Child: 26602; Corpse: 26601; Status = 0x4200 - waited
PID 26602 - exiting with status -872349885 (0xCC00FF43)
Signal 20 from PID 26602 (status 0xCC00FF43; UID 501)
Child: 26603; Corpse: 26602; Status = 0x4300 - waited
PID 26603 - exiting with status -872349884 (0xCC00FF44)
Signal 20 from PID 26603 (status 0xCC00FF44; UID 501)
$

删除对 nanosleep() 的一毫秒调用后,输出看起来像:

With the one millisecond call to nanosleep() removed, the output is apt to look like:

$ sigexit73
sigexit23
PID 26621 - exiting with status -872349888 (0xCC00FF40)
Signal 20 from PID 26621 (status 0xCC00FF40; UID 501)
Child: 26622; Corpse: 26621; Status = 0x4000 - waited
PID 26622 - exiting with status -872349887 (0xCC00FF41)
PID 26623 - exiting with status -872349886 (0xCC00FF42)
Signal 20 from PID 26622 (status 0xCC00FF41; UID 501)
Child: 26624; Corpse: 26623; Status = 0x4200 - waited
Signal 20 from PID 26623 (status 0xCC00FF42; UID 501)
Child: 26625; Corpse: 26622; Status = 0x4100 - waited
PID 26624 - exiting with status -872349885 (0xCC00FF43)
PID 26625 - exiting with status -872349884 (0xCC00FF44)
$

注意这里只有三行以Signal开头,也只有三行以waited结尾;一些信号和退出状态丢失.这很可能是因为 SIGCHLD 信号被设置到父进程之间的时间问题.

Note that there are only three lines starting Signal here, and also only three lines ending waited; some of the signals and exit statuses are lost. This is likely to be because of timing issues between the SIGCHLD signals being set to the parent process.

但是,关键是在代码使用sigaction()SIGCHLD<时exit()状态可以传输4个字节的数据/code>, SA_SIGINFO 跟踪状态.

However, the key point is that 4 bytes of data can be transmitted in the exit() status when the code uses sigaction(), SIGCHLD, SA_SIGINFO to track the status.

为了记录,测试是在运行 macOS Mojave 10.14.6 的 MacBook Pro 上执行的,使用 GCC 9.2.0 和 XCode 11.3.1.该代码也可以在我的 SOQ(堆栈溢出问题)存储库中作为文件 sigexit73 在 GitHub 上找到.csrc/so-1843-7779 子目录.

Just for the record, the testing was performed on a MacBook Pro running macOS Mojave 10.14.6, using GCC 9.2.0 and XCode 11.3.1. The code is also available in my SOQ (Stack Overflow Questions) repository on GitHub as file sigexit73.c in the src/so-1843-7779 sub-directory.

这篇关于ExitCodes 大于 255,可能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆