You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用posix_spawn为非标准文件描述符创建管道时的异常问题求助

posix_spawn为非标准文件描述符创建管道时的异常问题求助

大家好,我现在遇到一个关于posix_spawn创建管道的问题,想请各位帮忙排查一下。

我在macOS上尝试用posix_spawn启动进程(原本目标是Chrome,目前先用简单的Python脚本测试),需要为描述符1(STDOUT)、2(STDERR),以及自定义的描述符3(用于读取)和4(用于写入)创建管道。

测试下来的情况是:描述符3可以正常读取数据,但描述符4完全无法访问——不管是尝试打开它还是用fcntl测试,都会抛出错误:OSError: [Errno 9] Bad file descriptor,启动Chrome时也会遇到同样的问题。

以下是我用来测试的Python代码:

#!/usr/bin/env python3
import os
import sys
import time
import fcntl

print("fcntl 3:", fcntl.fcntl(3, fcntl.F_GETFD))
print("fcntl 4:", fcntl.fcntl(4, fcntl.F_GETFD))

fd4 = os.fdopen(4, 'wb')
while True:
    print('Cycle')
    time.sleep(2)
    while chunk := os.read(3, 1024):
        print('REQ:', chunk.decode('utf8', errors='backslashreplace'), file=sys.stderr)
        fd4.write(b'FOO')

还有用来启动进程的简化版C++代码(基于posix_spawn实现):

#include "pipes.h"

#include <cerrno>
#include <cstring>
#include <spawn.h>
#include <stdio.h>
#include <sys/poll.h>
#include <sys/wait.h>

extern "C" char** environ;

constexpr int CDP_WRITE_FILENO = 3;
constexpr int CDP_READ_FILENO = 4;

void RunBrowser(const char* exePath, const std::vector<const char*>& launchArgs) {
    posix_spawn_file_actions_t childFdActions{};
    posix_spawn_file_actions_init(&childFdActions);
    DEFER(&childFdActions) {
        posix_spawn_file_actions_destroy(&childFdActions);
    };

    int stdoutPipe[2];
    int stderrPipe[2];
    int cdpWritePipe[2];
    int cdpReadPipe[2];
    if (pipe(stdoutPipe) || pipe(stderrPipe) || pipe(cdpWritePipe) || pipe(cdpReadPipe)) {
        throw TBrowserError() << "Could not create a pipe: " << std::strerror(errno);
    }
    posix_spawn_file_actions_addclose(&childFdActions, stdoutPipe[0]);
    posix_spawn_file_actions_addclose(&childFdActions, stderrPipe[0]);
    posix_spawn_file_actions_addclose(&childFdActions, cdpWritePipe[1]);
    posix_spawn_file_actions_addclose(&childFdActions, cdpReadPipe[0]);
    posix_spawn_file_actions_adddup2(&childFdActions, stdoutPipe[1], STDOUT_FILENO);
    posix_spawn_file_actions_adddup2(&childFdActions, stderrPipe[1], STDERR_FILENO);
    posix_spawn_file_actions_adddup2(&childFdActions, cdpWritePipe[0], CDP_WRITE_FILENO);
    posix_spawn_file_actions_adddup2(&childFdActions, cdpReadPipe[1], CDP_READ_FILENO);
    posix_spawn_file_actions_addclose(&childFdActions, stdoutPipe[1]);
    posix_spawn_file_actions_addclose(&childFdActions, stderrPipe[1]);
    posix_spawn_file_actions_addclose(&childFdActions, cdpWritePipe[0]);
    posix_spawn_file_actions_addclose(&childFdActions, cdpReadPipe[1]);

    pid_t childPid{};
    if (const int ret = posix_spawn(&childPid, exePath,
                                    &childFdActions, nullptr,
                                    const_cast<char* const*>(launchArgs.data()),
                                    environ)) {
        throw TBrowserError() << "Failed to spawn a process: " << std::strerror(ret);
    }

    close(stdoutPipe[1]);
    close(stderrPipe[1]);
    close(cdpWritePipe[0]);
    close(cdpReadPipe[1]);

    int status;
    do {
        const int ret = waitpid(childPid, &status, WUNTRACED | WCONTINUED);
        if (ret == -1) {
            kill(childPid, SIGKILL);
            throw TBrowserError() << "waitpid error: -1";
        }

        if (WIFEXITED(status)) {
            const auto retCode = WEXITSTATUS(status);
            if (retCode == 0) {
                break;
            }
            throw TBrowserError() << std::format("Browser process failed with exit code {}", retCode);
        }

        if (WIFSIGNALED(status)) {
            throw TBrowserError() << "Browser process killed by signal " << WTERMSIG(status);
        }

        if (WIFSTOPPED(status)) {
            std::cerr << "Browser process stopped by signal " << WSTOPSIG(status) << std::endl;
        }

        if (WIFCONTINUED(status)) {
            std::cerr << "Browser process is continued" << std::endl;
        }
    } while (WIFEXITED(status) || WIFSIGNALED(status));
}

备注:内容来源于stack exchange,提问作者andre487

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:14:33