Beispiel #1
0
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The 
 *     handler reaps all available zombie children, but doesn't wait 
 *     for any other currently running children to terminate.  
 */
void 
sigchld_handler(int sig) 
{
    pid_t cpid;
    int status;
    struct job_t* job;
    sigset_t mask,prev;
    //the reason why i dn not use the wrapped function
    //is that i need the return value
    while ((cpid = waitpid(-1, &status,WNOHANG|WUNTRACED))>0) {
        //prepare the mask
        Sigfillset(&mask);
        //block the signal because  i want to change something
        Sigprocmask(SIG_BLOCK, &mask, &prev);
        //get the job by the pid
        job = getjobpid(job_list, cpid);
        //STP by any signal
        //change thet status and print msg
        if (WIFSTOPPED(status)) {
            printf("Job [%d] (%d) stopped by signal %d\n",job->jid, cpid, WSTOPSIG(status));
            job->state = ST;
        }
        //terminate by signal
        //delete the job and print msg
        else if (WIFSIGNALED(status)){
            printf("Job [%d] (%d) terminated by signal %d\n",job->jid, cpid, WTERMSIG(status));
            deletejob(job_list, cpid);
        }
        //terminate normally
        //just delete the job from the job list
        else
            deletejob(job_list, cpid);        
    }
    return;
}
Beispiel #2
0
/*
 * builtin_cmd - If the user has typed a built-int
 *    command then execute it immediately.
 *    quit, fg, bg, jobs
 */
int builtin_cmd(char **argv)
{
    char *cmd = argv[0];
    sigset_t mask, prev;

    /* Blocks all signals while determining
     * whether command is built in
     */
     Sigfillset(&mask);
     Sigprocmask(SIG_BLOCK, &mask, &prev);

    if (!strcmp(cmd, "quit")) {
        Sigprocmask(SIG_SETMASK, &prev, NULL);
        exit(0);
    }
    if (!strcmp(cmd, "jobs")) {
        listjobs(jobs);
        Sigprocmask(SIG_SETMASK, &prev, NULL);
        return 1;
    }
    if (!strcmp(cmd, "bg") || !strcmp(cmd, "fg")) {
        Sigprocmask(SIG_SETMASK, &prev, NULL);
        do_bgfg(argv);
        return 1;
    }

    Sigprocmask(SIG_SETMASK, &prev, NULL);
    return 0;
}
Beispiel #3
0
Datei: tsh.c Projekt: fffxj/csapp
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int sig) 
{
  int olderrno = errno;
  sigset_t mask_all, prev_all;
  pid_t pid;
  int status;
  
  Sigfillset(&mask_all);
  while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) {
    Sigprocmask(SIG_BLOCK, &mask_all, &prev_all); /* Block Signals*/
    if (WIFEXITED(status)) {    /* Exit normally */
      deletejob(jobs, pid);
    }
    if (WIFSIGNALED(status)) {  /* C-c SIGINT */
      printf("Job [%d] (%d) terminated by signal 2\n", pid2jid(pid), pid);
      deletejob(jobs, pid);     /* Note: printf first, then deletejob */
    }
    if (WIFSTOPPED(status)) {   /* C-z SIGTSTP */
      printf("Job [%d] (%d) stopped by signal 20\n", pid2jid(pid), pid);
      getjobpid(jobs, pid)->state = ST;
    }
    Sigprocmask(SIG_SETMASK, &prev_all, NULL); /* Unblock Signals*/
  }

  errno = olderrno;
  return;
}
Beispiel #4
0
/*
 * eval - Evaluate the command line that the user has just typed in
 *
 * If the user has requested a built-in command (quit, jobs, bg or fg)
 * then execute it immediately. Otherwise, fork a child process and
 * run the job in the context of the child. If the job is running in
 * the foreground, wait for it to terminate and then return.  Note:
 * each child process must have a unique process group ID so that our
 * background children don't receive SIGINT (SIGTSTP) from the kernel
 * when we type ctrl-c (ctrl-z) at the keyboard.
 */
void
eval(char *cmdline)
{
    int bg;              /* should the job run in bg or fg? */
    struct cmdline_tokens tok;
    sigset_t mask_one, prev_one, mask_all;
    int state;
    pid_t pid;

    /* Parse command line */
    bg = parseline(cmdline, &tok);

    if (bg == -1) /* parsing error */
        return;
    if (tok.argv[0] == NULL) /* ignore empty lines */
        return;

    /* Fig. 8.40 */ 
    if (tok.builtins == BUILTIN_NONE) {
      Sigfillset(&mask_all);
      Sigemptyset(&mask_one);
      Sigaddset(&mask_one, SIGCHLD);
      Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */
      
      if ((pid = Fork()) == 0) {
          Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
	  if (execve(tok.argv[0], tok.argv, environ) < 0) {
	      printf("%s: Command not found.\n", tok.argv[0]);
	      exit(0);
	  }
      }

      /* Parent process */
      Sigprocmask(SIG_BLOCK, &mask_all, NULL); /* Block all */
      state = bg ? BG : FG;
      addjob(job_list, pid, state, cmdline);
      Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
            
      if (state == BG) {
          printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
      }	else {
	
      }
      // Sigprocmask(SIG_SETMASK, &prev_one, NULL);
    }

    return;
}
Beispiel #5
0
Datei: tsh.c Projekt: fffxj/csapp
/* 
 * eval - Evaluate the command line that the user has just typed in
 * 
 * If the user has requested a built-in command (quit, jobs, bg or fg)
 * then execute it immediately. Otherwise, fork a child process and
 * run the job in the context of the child. If the job is running in
 * the foreground, wait for it to terminate and then return.  Note:
 * each child process must have a unique process group ID so that our
 * background children don't receive SIGINT (SIGTSTP) from the kernel
 * when we type ctrl-c (ctrl-z) at the keyboard.  
*/
void eval(char *cmdline) 
{
  char *argv[MAXARGS]; /* Argument list execve() */
  char buf[MAXLINE];   /* Holds modified command line */
  int bg;              /* Should the job run in bg or fg? */
  pid_t pid;           /* Process id */

  sigset_t mask_all, mask_one, prev_one; /* Signal mask */
  Sigfillset(&mask_all);
  Sigemptyset(&mask_one);
  Sigaddset(&mask_one, SIGCHLD);

  strcpy(buf, cmdline);
  bg = parseline(buf, argv); 
  if (argv[0] == NULL)  
    return;   /* Ignore empty lines */

  if (!builtin_cmd(argv)) {
    Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */
    if ((pid = Fork()) == 0) {       /* Child runs user job */
      Sigprocmask(SIG_SETMASK, &prev_one, NULL);  /* Unblock SIGCHLD */
      setpgid(0, 0);
      if (execve(argv[0], argv, environ) < 0) {
        printf("%s: Command not found\n", argv[0]);
        exit(0);
      }
    }
    if (!bg) {         /* Parent waits for foreground job to terminate */    
      Sigprocmask(SIG_BLOCK, &mask_all, NULL);
      addjob(jobs, pid, FG, cmdline);
      Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
      waitfg(pid);
    }
    else {             /* Background job */
      Sigprocmask(SIG_BLOCK, &mask_all, NULL);
      addjob(jobs, pid, BG, cmdline);
      printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
      Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
    }      
  }
  return;
}
Beispiel #6
0
/*
 * eval - Evaluate the command line that the user has
 *    just typed in
 *
 * If the user has requested a built-in command (quit, jobs,
 *    bg or fg) then execute it immediately. Otherwise, fork a
 *    child process and run the job in the context of the child.
 *    If the job is running in the foreground, wait for it to
 *    terminate and then return.
 *
 * Note: each child process must have a unique process
 *    group ID so that our background children don't receive
 *    SIGINT (SIGSTP) from the kernel
 *    when we type ctrl-c (ctrl-z) at the keyboard.
 */
void eval(char *cmdline)
{
    char *argv[MAXARGS], buf[MAXLINE];
    int bg, status, state;
    volatile pid_t pid;
    int jid;
    sigset_t mask_all, mask_one, prev_one;

    Log("EVAL [0]\n", 9);

    strcpy(buf, cmdline);
    bg = parseline(buf, argv);

    if (argv[0] == NULL) {
        return;
    }

    Log("EVAL [1]\n", 9);

    if (builtin_cmd(argv)) {
        return;
    }

    Log("EVAL [2]\n", 9);

    Sigfillset(&mask_all);
    Sigemptyset(&mask_one);
    Sigaddset(&mask_one, SIGCHLD);

    Sigprocmask(SIG_BLOCK, &mask_one, &prev_one);

    pid = Fork();

    if (pid == CHILD) {
        Sigprocmask(SIG_SETMASK, &prev_one, NULL);
        Setpgid(0, 0);
        Log("EVAL [3]\n", 9);
        Execve(argv[0], argv, environ);
    }

    Sigprocmask(SIG_BLOCK, &mask_all, NULL);

    state = bg ? BG : FG;

    Log("EVAL [4]\n", 9);

    status = addjob(jobs, pid, state, cmdline);

    Log("EVAL [5]\n", 9);

    /* Stores jid while process has not been removed */
    jid = getjobpid(jobs, pid)->jid;

    atomic_fggpid = bg ? 0 : pid;

    Log("EVAL [5a]\n", 10);

    Sigprocmask(SIG_SETMASK, &prev_one, NULL);

    Log("EVAL [5b]\n", 10);

    /* Handle errors when generating a new job */
    if (!status) {
        return;
    }

    /* Parent waits for foreground job to terminate */
    if (!bg) {
        Log("EVAL [6]\n", 9);
        waitfg(pid);
    }
    else {
        Log("EVAL [7]\n", 9);
        printf("[%d] (%d) %s", jid, pid, cmdline);
    }
}