Vfork

上次說的vfork完, 不能在close fd, 看來是錯的?

From "The Linux Programming Interface":
There are a few things that the child process can do between vfork() and exec()
without affecting the parent. Among these are operations on open file descriptors
(but not stdio file streams). Since the file descriptor table for each process is main-
tained in kernel space (Section 5.4) and is duplicated during vfork(), the child process can perform file descriptor operations without affecting the parent.
- Comment - Hang out - ShareTranslate

Scott Tsai - 確實是我錯了:POSIX 中 vfork() 的限制如我上次所說,只能紀錄傳回 pid 而後就要呼叫 exec() 或 _exit() 。Linux 上較寬鬆, 至少可以呼叫 close() ,因為 child process 有自己的 kernel space fd table。(用 dup2() 作 I/O 重導應 ok)

TLPI 也不明確列出 vfork() 後到底能夠作哪些動作,關鍵困難是 vfork() 後 parent 停止執行,但 child 與 parent 共享全部 user space 記憶體,包括 stack。故 child 不能 return 回上層函式(會摧毀 parent 的 stack)、不能呼叫 exit() 只能用 _exit() (前者會 flush STDIO buffers)、若 signal handler 在 child 中執行,也不能動到記憶體,否則會影響 parent。

記住 vfork() 不複製 user space pages, parent 會停止執行直到 child exec() 或 _exit() 有助於理解這些限制,但還是非常細微、易錯。
6:13 PM (edited)

Scott Tsai - 例一. vfork() 後 child 與 parent 共享全部 user space 記憶體所造成的 bug: http://sourceware.org/git/?p=glibc-ports.git;a=commit;h=3680f14a7d12a9faa86e09aaea1b3aa20713355e

這是只影響 HP PA-RISC 的舊 bug 但看一下就可以體會『不經意共享記憶體 bug』的口味。
5:59 PM (edited) Translate

Che-Liang Chiou - A dumb question:

Since it is unlikely to require all signal handlers not touching memory (a signal handler should be quite useless if it cannot write to memory), how are we sure that all of the child's signal handlers not called?

My most-likely-incorrect understanding is this:

  • A child process inherits its parent's signal handlers and signal masks
  • A signal could be sent to a process group, and in this case, the parent and its children receive the signal
  • On receiving the signal, the child's signal handler is called, and we are screwed.

So if after a vfork() but before a exec(), how does the child process make sure that none of its signal handlers is called?

I guess the only solution here is that the parent process set masks before calling vfork() and unset masks after vfork() returns?
6:00 PM

Scott Tsai - +Che-Liang Chiou: the only solution here is that the parent process set masks before calling vfork() and unset masks after vfork() returns?

I believe so, it's been recommended by knowledgeable folks: https://lkml.org/lkml/2010/11/4/206

I'm missing Google Code Search again. I'd like to see real world vfork() examples that defines the de-facto API of what needs to be supported.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License