1

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.

pilcrow
  • 56,591
  • 13
  • 94
  • 135
matheuscscp
  • 827
  • 7
  • 23
  • Or prevent them from being inherited, if you have that `ioctl()` option available to you. – user207421 Sep 03 '15 at 02:47
  • @AndrewMedico, the child image [has only one running thread](http://stackoverflow.com/q/6056903/132382). – pilcrow Sep 03 '15 at 13:44
  • Just to clarify @EJP's remark, `ioctl(FIOCLEX)` (or its more portable cousin, `fcntl(FD_CLOEXEC)`) will close descriptors across `exec` but not across a `fork`. In the case where your child program `system()`s, the child itself would still have open fds inherited from the parent. – pilcrow Sep 03 '15 at 14:13

1 Answers1

3

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.

pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • What happens when Linux receives a TCP segment? It forwards to both PID 100 and PID 101? If only "copy of forky" is running on PID 101, PID 101 won't be able to catch any data from any TCP sockets, right? But, could it? If, for instance, "copy of forky" has the file descriptor, coult it call accept() and successfully handle a TCP connection? Like, two processes handling the same TCP server! Oh my god! – matheuscscp Sep 03 '15 at 04:35
  • But, is it okay if I don't touch any descriptors or any network syscalls or whatever inside PID 101? My system is working well... I'm just afraid of future problems. PID 101 only exists to call system() and then die immediately. – matheuscscp Sep 03 '15 at 04:43
  • That's why I call exit(system(cmd)), hahaha. – matheuscscp Sep 03 '15 at 04:44