Reputation: 81
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
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