Trouble with status of pid after waitpid in my own implemented shell

I am trying to implement my own shell as a homework. In the shell I need a new command called 'status' which displays the current status of pids for example:

When I type it must display

myshell>>status

PID PGID STATUS PROG

1412 1412 pwd exit(0)

1454 1454 /opt/firefox/bin/firefox running

1462 1462 ls exit(1)

1463 1463 xterm stopped

However in my shell I have no child process error for exited process and it writes signaled(29) for stopped process.You can see my output from here

This is my process list struct

typedef struct 
{
  pid_t ppid;
  pid_t ppgid;
  char *prog;
  char status[30];
}Process;

This is my fork for executing new process:

if(forkexec){
    int pid=fork();
    iterator=iterator+1;
    processList[iterator].prog=ptr;
    processList[iterator].ppid=pid;
    processList[iterator].ppgid=getpgid(pid); 
    strcpy(ptr,worte[0]);

    switch (pid){
    case -1:
      perror("Fehler bei fork"); 
      return(-1);
    case 0: //child process

      if(umlenkungen(k))
    exit(1);
      if(!setpgid(0, 0))
      {
        do_execvp(k->u.einfach.wortanzahl, k->u.einfach.worte); //for executing program
      }

      abbruch("interner Fehler 001"); //error
    default: //parent process
      if(k->endeabwarten){
        if(!setpgid(pid, 0))
        {
          tcsetpgrp(0,getpgid(pid));
          waitpid(pid, NULL, WUNTRACED);
          tcsetpgrp(0,getpgid(shellpid));
        }

      }
      return 0;
    }
  }

In child process it calls do_execvp function which is:

void do_execvp(int argc, char **args){
  if(execvp(*args, args)==-1)
  {
   perror("exec-Fehler");
  fprintf(stderr, "bei Aufruf von \"%s\"\n", *args);
  exit(1); 
  } 
}

For new status command I have, it means if the user enter status this part will run:

if (strcmp(worte[0], "status")==0) { 
    int i;
    fputs("PID: PGID: PROGRAM: STATUS: \n",stdout);
    for(i=0; i<=iterator; i++)
      {
      find_status(i);
      printf("%d %d %s %s\n", processList[i].ppid,processList[i].ppgid,processList[i].prog,processList[i].status);
      }
      return 0;
  }

When I am iterating the process list to print with upper code I also call find_status function which is:

void find_status(int current)  

{
  pid_t w;
  int status;
  char stat[30];

  w=waitpid(processList[current].ppid, &status, WNOHANG | WUNTRACED | WCONTINUED);

  switch(w){
      case -1: 
      strcpy(stat, "No child process");
      break;

      case 0:
         strcpy(stat,"running");
      default:
            if (WIFEXITED(status)!=0) {
                sprintf(stat, "exit(%d)", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)!=0) {
                sprintf(stat, "signaled(%d)", WTERMSIG(status));
            } else if (WIFSTOPPED(status)!=0) {
                strcpy(stat,"stopped");
            } 
      break;
  }
  strcpy(processList[current].status, stat);
}

By the way iterator variable is global variable which holds the index of the last element in the process list. Process list is also global variable. So, where is my mistake in the code why it is not displaying exited and stopped process' status? Thank you.

Upvotes: 0

Views: 503

Answers (1)

Gil Hamilton
Gil Hamilton

Reputation: 12337

Impossible to be sure since you haven't shown all the code, but I speculate that you've already waited for those processes.

In your fork code, the parent branch (default case) has a waitpid call. Is that code being executed? Once you have successfully waited for a child process (at least one that has in fact exited), it will be removed from the kernel process table, and you can't (successfully) later call waitpid again: it no longer exists.

To discover what exactly is going on, you should print the errno value when waitpid fails (even better, print strerror(errno) so that you don't have to go lookup the errno value). This will tell you exactly why waitpid failed, not just that it failed.

Upvotes: 1

Related Questions