【问题标题】:sharing perror among multiple forked processes在多个分叉进程之间共享错误
【发布时间】:2012-07-24 15:31:46
【问题描述】:

在 POSIX / Linux 中的多个分叉进程之间共享标准错误是否有任何缓冲区限制或特定准则?

perror("Some descriptor related error: ");

我有一个服务器应用程序,它在需要时调用 perror。作为一个单一的过程,它工作正常。如果使用fork创建了多个进程,服务器运行一段时间后(发生多次打印错误),它开始连续打印错误语句并进入无限循环。

我通过注释掉服务器正常运行的打印语句来验证。

所以在我看来,标准错误可能存在一些缓冲区溢出类型的场景,该场景会在一段时间后耗尽。

我没有对 perror 使用任何互斥锁或信号量。

服务器代码很大,它使用 epoll 处理多个客户端描述符,其中包含一个工作进程池,这些进程池会在客户端到来时获取它们。

【问题讨论】:

    标签: c linux concurrency posix fork


    【解决方案1】:

    您确实需要记住,虽然 I/O 可能是线程安全的,具体取决于平台,但输出到 stderrstdout 不是 多进程安全 ...因此如果您有多个进程写入终端输出,如果没有进程间同步机制使每个写入原子化,它们最终将相互覆盖。当我说“原子”时,我指的是你想写出每个进程的每条消息的整个长度......你最终可能会得到来自不同进程的每条消息的碎片作为每个人都访问终端缓冲区并以原子方式写入多个字节,但不是每个消息中的全部字节数,然后才不得不屈服于争夺终端缓冲区资源的下一个进程。

    现在,您的无限循环可能是由单个进程引起的……如果您注释掉所有错误语句,您怎么知道服务器“完美”地工作?例如,如果只有一个分叉的进程死锁,其余的进程可能都很好,服务器看起来“正常”运行,而实际上你只是掩盖了错误,而不是消除了它。

    【讨论】:

    • 谢谢,我明白了。但是我可以依靠这样一个事实,因为输出看起来完全完整和连续,即在无限循环打印错误开始之前根本不会被覆盖,所以这种覆盖不是原因吗?我的意思是我应该看到一些重叠的打印?而不是连续重复但完整的错误控制台打印?
    • 虽然问题是关于多处理,而不是多线程,stdio库通常是线程安全的(GNU libc实现当然is) -- 如果您同时从多个线程调用fprintf,则两条消息将按某种顺序序列化,但每条消息都是完整且完整的。 write(2) 系统调用是原子的,因此从多个进程同时写入同一个文件描述符再次表现良好,您只是不知道写入发生的顺序。
    • 即使stderr 存在缓冲区溢出问题,终端进程中输出缓冲区使用的内存也不会与正在运行的进程的内存共享,因此您不会损坏如果终端缓冲区存在这样的错误,则您正在运行的进程的堆或堆栈......重复打印的错误很可能是其中一个正在运行的分叉进程进入无限循环的问题。
    • @AdamRosenfield 写入在一定的消息长度内只是原子性的,对吗?
    • @AdamRosenfield 显然根据这个问题 (stackoverflow.com/questions/594851/is-fprintf-thread-safe),来自不同进程(即分叉进程)对 write() 的调用不是“安全的”
    猜你喜欢
    • 2013-10-12
    • 1970-01-01
    • 2012-07-22
    • 2011-09-29
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 2012-04-12
    相关资源
    最近更新 更多