Call system() inside forked (child) proces

2019-08-15 05:37发布

I have a program that have many threads. Some threads are TCP servers... Each server fires new threads to handle any new connections.

Inside one of the threads that handles a single client, I call fork(). The child process calls setpgid() (to create a new group) and then system() (the function of C/C++ standard library). The parent process keeps taking naps (usleep() function) and checking a time limit. If the time limit is exceeded before child process returns from system(), the parent SIGKILLs the child.

I'm using: Linux (Ubuntu), pthreads, etc. Nothing but C/C++ standard library!

My questions: what happens with all the threads and TCP sockets on the child process? Are these things inherited from the parent process? Will both child and parent run all these threads and TCP servers simultaneously? It would make no sense to me... And when parent SIGKILLs child, will the sockets be closed only inside child, or also in the parent?

Currently, I'm actually using exec() to clean the whole image of the child process, but I'd rather call system() directly if it's safe.

1条回答
爷的心禁止访问
2楼-- · 2019-08-15 06:23

File descriptors (a.k.a. fds) such as TCP sockets are inherited across a fork. The file or device "behind" them generally remains open and serviceable until the last file descriptor to it is closed or dismissed at process termination. Thus SIGKILL'ing the child won't affect the TCP sockets shared with the parent.

Only the fork()ing thread is executing in the child, however. The other threads of control are not copied. Your situation looks something like this:

+-- PID 100 -------------+ # parent
| fds: 0, 1, 2, 3 ... N  | # fds: stdin, stdout, stderr, socket ... socket
| threads:               |
|      0 (main)          |
|      1 (tcp server)    |
|      2 (forky)  ---------(fork(2))-+
|      ...               |           |
|      N (tcp server)    |           |
+------------------------+           |
                                     |
                                     |
                     +-- PID 101 -------------+ # child
                     | fds: 0, 1, 2, 3 ... N  | # fds: inherited
                     | threads:               |
                     |      0 (copy of forky) | # will exec() ?
                     +------------------------+

Calling exec will replace the PID 101 process image with some text's main() (and close any file descriptors marked FD_CLOEXEC). Calling system("whatever"), by contrast, would probably spawn at least two more processes: a (grand)child /bin/sh and a (great) grandchild "whatever".

It's very easy to confound yourself mixing threads, forks, and shared resources, especially if old, old interfaces like system() are thrown into the mix. Go slowly, explicitly discard resources you don't need when you don't need them, and troubleshoot one thing at a time.

查看更多
登录 后发表回答