wait() returns -1, errno=10 启动 Python 进程后

wait() returns -1, errno=10 after launching Python process

我有一个在线程上启动 Python 进程的 C 程序。 Python 进程使用 Selenium 并向 FTC 提交了骚扰电话投诉。由于Python内存泄漏,posix_spawn用于保持C程序和Python进程分离。我在管理 Python 流程时遇到问题。

Python 进程的 wait() 正在 returning -1errno 设置为 10。根据 wait(2) man page 这是一个错误。我相信 10ECHILDstrerror returns No child processes.

$ ./test.exe
Process started, pid 2730
call_datetime: 2019-04-04 18:07:00
caller_name: PERRYVILLE   MD
caller_number: 4106425608
Wait failed -1, 10

运行 Python 直接使用脚本生成预期的 0 return 代码。

$ python3 ftc.py --caller_name "PERRYVILLE   MD" --caller_number 4106425608 --call_datetime "2019-04-04 18:07:00"
call_datetime: 2019-04-04 18:07:00
caller_name: PERRYVILLE   MD
caller_number: 4106425608
$ echo "$?"
0

我发现了两个类似的问题。第一个位于 Linux system() returns -1, ERRNO = 10 No child processes. There is not enough information in the question and it was closed. The second question is at 。我不认为这个问题适用,因为 SIGCHLD 没有被处理。

为什么 waitECHILD 而失败?


这是C程序。它调用 Python 脚本然后退出。

等待代码取自 wait(2) man page 示例。

$ cat test.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>
#include <spawn.h>
#include <sys/types.h>
#include <sys/wait.h>

#define log_error printf
#define log_info printf
extern char **environ;

int main(int argc, char* args[])
{
    char* const cname = "PERRYVILLE   MD";
    char* const cnumber = "4106425608";
    char* const ctime = "2019-04-04 18:07:00";

    char* const arguments[] = {
        "python3",
        "ftc.py",
        "--caller_name", cname,
        "--caller_number", cnumber,
        "--call_datetime", ctime,
        NULL
    };

    pid_t pid;
    int res = posix_spawn(&pid, "/usr/bin/python3", NULL, NULL, arguments, environ);

    if (res != 0) {
        log_error("Process failed %d, %d\n", res, errno);
        goto do_exit;
    } else {
        log_info("Process started, pid %d\n", pid);
    }

    do
    {
        res = waitpid(pid, &res, WUNTRACED | WCONTINUED);
        if (res == -1) {
            log_error("Wait failed %d, %d\n", res, errno);
            goto do_exit;
        }

        if (WIFEXITED(res)) {
            log_info("Process exited, result %d\n", WEXITSTATUS(res));
        //} else if (WIFSIGNALED(res)) {
        //    log_info("Process signaled, result %d\n", WTERMSIG(res));
        } else if (WIFSTOPPED(res)) {
            log_info("Process stopped, result %d\n", WSTOPSIG(res));
        } else if (WIFCONTINUED(res)) {
            log_info("Process continued\n");
        }
    } while (!WIFEXITED(res) /*&& !WIFSIGNALED(res)*/);

do_exit:

    return (int)WEXITSTATUS(res);
}

C代码用gcc -Wall -D_GNU_SOURCE -g3 -O1 -std=c99 -pthread test.c -o test.exe编译。

这里是 Python 脚本的相关部分。它打印脚本参数然后退出。

$ cat ftc.py
#!/usr/bin/env python3

import time
import sys

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

def get_option(argv, option):

    argc = len(argv)
    for i in range(0, argc-1):
        if (argv[i] == option and i+1 < argc):
            return argv[i+1]

    return None

def main():

    caller_name = get_option(sys.argv, "--caller_name")
    caller_number = get_option(sys.argv, "--caller_number")
    call_datetime = get_option(sys.argv, "--call_datetime")

    if caller_name is None:
        sys.exit("caller_name is not available")
    if caller_number is None:
        sys.exit("caller_number is not available")
    if call_datetime is None:
        sys.exit("call_datetime is not available")

    print(f"call_datetime: {str(call_datetime)}")
    print(f"caller_name: {str(caller_name)}")
    print(f"caller_number: {str(caller_number)}")

    sys.exit(0)

if __name__ == "__main__":
    main()

您正在用 waitpid() 中的 return 值覆盖等待状态:

    res = waitpid(pid, &res, WUNTRACED | WCONTINUED);

对 return 值和等待状态使用不同的变量:

    int ret = waitpid(pid, &res, WUNTRACED | WCONTINUED);
    if (ret == -1) {
        log_error("Wait failed %d, %d\n", ret, errno);
        goto do_exit;
    }