Skip to content
Advertisement

Wait for signal from parent and does job and blocks again

Write a program that can display a text string (consisting only of the 26 alphabets and spaces). The program should fork 27 worker processes. Each worker process runs an infinite loop in which it waits for a signal from the controller (i.e., parent), sleeps for 1 sec, prints its pre-defined character, signals the controller, then blocks again. The controller reads a string from the keyboard, then signals the workers in the correct order to get the string displayed The following is my code, but I am not getting output, it isn’t printing anything.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
#include <string.h>
int
main()
{
  /*...declarations and stuff....*/
  scanf("%s",inputString);
  length=strlen(inputString);
  for (i=0;i<27;i++)
  {
    pid[i]=fork();
    if (pid[i]==0)
     {
       /*...Declare my character...*/
       while (1)
       {
          pause();
          sleep(1);
          printf("%c",myChar);
          kill(ppid,SIGCONT);
       }
       return 0;
     }
  }
  for (i=0;i<length;i++)
  {
    int temp=inputString[i];
    if (temp==32)
    {
      kill(pid[0],SIGCONT);
    }
    else
    {
      kill(pid[temp-96],SIGCONT);
    }
    pause();
  }
  for(i=0;i<27;i++)
    kill(pid[i],SIGTERM);
  return 0;
}

Advertisement

Answer

  1. First never use SIGCONT or another signal like this for custom usage. Prefer using SIGUSR1 and SIGUSR2. SIGCONT has some special semantic.

  2. Now even if you change CONT to, say, USR1, the way you use pause() is a problem. After the child process been awaked, it will be killed because you didn’t catched signals. Manual says:

pause() causes the calling process (or thread) to sleep until a signal is delivered that either terminates the process or causes the invocation of a signal-catching function.

  1. Children will never signal the right process as you did not set ppid to a correct value.

  2. You will never experienced printings correctly because writes are buffered and there is no flushing. Either use printf("%c",myChar); fflush(stdout); or printf("%cn",myChar);

That will lead to something like:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>  
#include <sys/types.h>
#include <string.h>

void handler(int sig) {
}

int main() {
  pid_t ppid;
  int length;
  char inputString[256];
  pid_t pid[256];
  int i;
  char myChar;
  scanf("%s",inputString);
  length=strlen(inputString);
  struct sigaction action;
  sigemptyset(&(action.sa_mask));
  action.sa_flags = 0;
  action.sa_handler = handler;
  sigaction(SIGUSR1,&action,NULL);
  ppid = getpid();
  for (i=0;i<27;i++) {
    pid[i]=fork();
    if (pid[i]==0) {
       myChar='a'+i;
       while (1) {
          pause();
          sleep(1);
          printf("%cn",myChar);
          kill(ppid,SIGUSR1);
       }
       return 0;
     }
  }
  for (i=0;i<length;i++) {
    int temp=inputString[i];
    if (temp==32) {
      kill(pid[0],SIGUSR1);
    }
    else {
      kill(pid[temp-'a'],SIGUSR1);
    }
    pause();
  }
  for(i=0;i<27;i++)
    kill(pid[i],SIGTERM);
  return 0;
}
  1. There is little much more thing to say, like why looping over 27?, etc, but these are actually minor problems (this not to say not to correct them later).
Advertisement