0

I am implementing a web server where I need to make the parent process do the following:

  • fork() new worker processes (a pool) at the beginning.
  • Looping forever, listening for incoming requests (via socket communication).
  • Putting the socket descriptor (returned by accept() function) into a queue.

and the worker process will do the following:

  • Once created, loops forever watching the queue for any passed socket descriptors.
  • If he takes the socket descriptor, he handles the request and serves the client accordingly.

After looking around and searching the internet, I found that I can send a file descriptor between different processes via UNIX Domain Socket or Pipes. But unfortunately, I can do this synchronously only! (I can send one fd at a time, and I cannot put it in a waiting queue)

So, my question is:

  • How can I make the parent process puts the socket descriptor into a waiting queue, so that, the request is pending until one of the worker processes finishes a previous request?
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • 1
    A better (and easier) solution is to have a mutex around the `accept` that each worker process has. i.e. as soon as the accept suceeds, the process unlocks the mutes giving another process a chance. – Ed Heal Dec 13 '11 at 16:37
  • @EdHeal The parent process is the one who uses `accept()` function – Eng.Fouad Dec 13 '11 at 16:43
  • 2
    @engFouad - Ass noted below your solution will not work. The one that I have outlined will work. (that is why it is a comment) – Ed Heal Dec 13 '11 at 16:45
  • I'll grant it's obscure, and it may not even be the best architecture, but I promise you passing file descriptors using `sendmsg` is a real, documented feature that genuinely does work (on at least some platforms, etc. etc.) – Useless Dec 13 '11 at 17:05
  • This is the correct answer (@EdHeal). Just before you call accept(), fork the process, and so all your children also calls accept(). But provide a mutex so only 1 process calls accept at a time. When you fork, you inherit all the file descriptors. – Lloyd Macrohon Dec 13 '11 at 18:43

2 Answers2

2

File descriptors are just integers. They are used to index into a per-process table of file information, maintained by the kernel. You can't expect a file descriptor to be "portable" to other processes.

It works (somewhat) if you create the files before calling fork(), since the file descriptor table is part of the process and thus clone()d when the child is created. For file descriptors allocated after the processes have split, such as when using accept() to get a new socket, you can't do this.

UPDATE: It seems there is a way, using sendmsg() with AF_UNIX sockets, see here for details as mentioned in this question. I did not know that, sounds a bit "magical" but apparently it's a well-established mechanism so why not go ahead and implement that.

Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 1
    There is, on Linux at least, a way to pass file descriptors between processes using pipes or UNIX domain sockets. I can't for the life of me remember the details, but I'm assuming the OP already has that part. – Useless Dec 13 '11 at 16:44
0
  1. put the fd on an internal queue (lock-free if you want, but probably not necessary)
  2. have a thread in the parent process which just reads an fd from the internal queue, and sends it via the pipe
  3. all child processes inherit the other end of the pipe, and compete to read the next fd when they finish their current job
Useless
  • 64,155
  • 6
  • 88
  • 132
  • 1
    This will not work - as noted above file descriptors are not universal and just relate to the current process. – Ed Heal Dec 13 '11 at 16:44
  • 1
    Yes it will - as also noted above, this seems to be part of the BSD spec. See, for example, [this](http://stackoverflow.com/questions/1788095/descriptor-passing-with-unix-domain-sockets). – Useless Dec 13 '11 at 16:50
  • 4
    @Ed Heal ,unwind: wrong, sendmsg can used to pass filedescriptors : http://stackoverflow.com/questions/909064/portable-way-to-pass-file-descriptor-between-different-processes – wildplasser Dec 13 '11 at 16:53