2

Additional to dynamic pool of process C

Changed code:

   int main(int argc, char *argv[])
    {
    ...//settings
    listensock = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
    result = bind(listensock, (struct sockaddr *) &sAddr, sizeof(sAddr));
    result = listen(listensock, 1);
    ...//skip errors checking

    while(1){
            newsock = accept(listensock, NULL,NULL);
            pid=fork();
            if (pid == 0) {
                send(newsock, buffer, nread, 0);
            }
            close(newsock);
    }
    wait(NULL);
}

This creates childs only if someone try to connect. It is not pre-fork model. N processes should be run after server starts and wait for connects. If I try to invoke fork() 3 times in loop, it immediately terminate. How to start, wait until someone connect and then send data (like in my code).

Community
  • 1
  • 1
Nat Kup
  • 109
  • 3
  • 11

2 Answers2

4

You can move the fork() to be before the accept() loop, after the listensock has been initialized.

for (int i = 0; i < 3; ++i) {
    int p = fork();
    if (p == 0) break;
    if (p < 0) { /* handle error... */ }
}
while (1) {
    newsock = accept(...);
    if (newsock < 0) { /* handle error... */ }
    else {
        send(newsock, ...);
        close(newsock);
    }
}
jxh
  • 69,070
  • 8
  • 110
  • 193
  • 1
    This is the cleaner answer. All of the four processes wait symmetrically on the same file descriptor, and it relies on the kernel to decide which one to wake up. – Andy Ross Apr 30 '13 at 16:58
  • @Andy Ross, but if 3 will be all running? how to add more? – Nat Kup Apr 30 '13 at 17:09
  • 1
    @NatKup: You change 3 to something more. Do you want pre-`fork()` or not? Typically, pre-`fork()` means "not dynamic". Make your question more clear. – jxh Apr 30 '13 at 18:00
3

The parent process should not accept but just select on that socket, and when data becomes available, wake up one of the children. The child will call accept.

Pseudocode:

for (i = 0; i < 3; ++i) 
{
   if ((thepid=fork()))
   {
      while (1)
      {
       wait_for_signal();
       int newsock=accept();
       process_socket(newsock);
      }

   }
   else
      pids[i] = thepid;
}
while (1) 
{
   select(...);
   send_wakeup_signal(pids[random()%3]);
}

There are several ways to send the wakeup signal (and to wait for one). One method is just kill(pid, signal_number) and pause(). Eventually however you will need to take the process off the ready pool and reinsert it back when it's done, because there's a possibility to send a wakeup to a process that is busy processing a previous request. This requires communication back from the children to the parent. You can do this with a named pipe or any other IPC mechanism. Look at the source code of the Apache web server to see the canonical industrial-strength example of this technique.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • but how to back to wait_for_signal state in child process after process_socket? It will be just terminated. And how to add process into pool if all children are busy. – Nat Kup Apr 30 '13 at 16:21
  • 1. The children should loop (code updated) 2. Children should report back to the parent when they are done through one iteration (not shown in the code). – n. m. could be an AI Apr 30 '13 at 16:30
  • Sorry,I meant how to add NEW process into pool(extend it) if all three are running. – Nat Kup Apr 30 '13 at 16:35
  • What's the problem? Just fork another one and add it. – n. m. could be an AI Apr 30 '13 at 16:42
  • The "wakeup signal" here is senseless. The children should simply call `accept()` themselves. Multiple processes can be blocked on `accept()` on the same file descriptor. The kernel will return from the syscall in exactly one of them. – Andy Ross Apr 30 '13 at 16:57
  • Note also that this solution will attempt to "wake up" a process that happens to be blocked on a long-running operation, even if there is an idle process available that the kernel would know about. – Andy Ross Apr 30 '13 at 17:00
  • @AndyRoss: that's a possibility but see e.g [here](http://stackoverflow.com/questions/1293652/accept-with-sockets-shared-between-multiple-processes-based-on-apache-prefork). – n. m. could be an AI Apr 30 '13 at 17:10
  • @n.m.: Linux no longer has that thundering herd problem. – jxh Apr 30 '13 at 18:19