Пример #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 pid;
    int status;

    while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0)
    {
        struct job_t *job = getjobpid(job_list, pid);
        if (WIFSIGNALED(status))
        {
            printf("Job [%d] (%d) terminated by signal %d\n", job->jid, pid, WTERMSIG(status));  
            deletejob(job_list, pid);
        }
        else if (WIFSTOPPED(status))
        {
            printf("Job [%d] (%d) stopped by signal %d\n", job->jid, pid, WSTOPSIG(status));  
            job->state = ST;
        }
        else
        {
            deletejob(job_list, pid);
        }
    }
    return;
}
Пример #2
0
Файл: tsh.c Проект: 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;
}
Пример #3
0
/* 
 * waitfg - Block until process pid is no longer the foreground process
 */
void waitfg(pid_t pid)
{
	int status;
	if ((pid = waitpid(pid, &status, WUNTRACED)) < 0)
	{
		perror("waitfg error:");
		exit(0);
	}
	else
	{
		if (WIFSTOPPED(status))
		{
			int jid = pid2jid(pid);	
			printf("Job [%d] %d stopped by signal: Stopped\n",jid,(int)pid);
		}
		else if (WIFEXITED(status))
		{
			deletejob(jobs,pid);
		}
		else if (WIFSIGNALED(status))
		{
			printf("Job %d terminated by signal: Interrupt\n",(int)pid);
			deletejob(jobs,pid);
		}
	}
    return;
}
Пример #4
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 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) 
{
    struct job_t *job;
    int status;
    pid_t pid;
    while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0) //returns pid of child if OK,0 or -1 on error
    {
	job = getjobpid(jobs,pid);
        if(WIFEXITED(status))
        {
          deletejob(jobs,pid);//deleting jobs if exited normally
        }
        if(WIFSIGNALED(status))
        {
          printf("Job [%d] (%d) terminated by signal %d\n",job->jid,pid,WTERMSIG(status));
          deletejob(jobs,pid); //deleting jobs terminated with signals
        }
        if(WIFSTOPPED(status))
        {
          printf("Job [%d] (%d) stopped by signal %d\n",job->jid,pid,WSTOPSIG(status));
          job->state = ST; //changing the state of stopped jobs to ST
        }
    }
    return;
}
Пример #5
0
void fg_waitpid(pid_t pid) {
	int status;
	pid_t r_pid;
	struct job *p;

	if ((r_pid = waitpid(pid, &status, 0)) > 0) {
		printf("fg_waitpid in, forepid=%d, r_pid=%d\n", forepid, r_pid);
		forepid = 0;
		if (WIFEXITED(status)) {
			deletejob(r_pid);
			fprintf(stderr, "job %d terminated normally with exit status=%d\n",
					r_pid, WEXITSTATUS(status));
		}
		else	if (WIFSTOPPED(status)) {
			p = selectjob(r_pid);
			p->state = 0;
			fprintf(stderr, "job [%d] %d stopped by signal: Stopped\n", 
					p->jid, r_pid);
		}
		else	if (WIFSIGNALED(status)) {
			deletejob(r_pid);
			fprintf(stderr, "job %d terminated by ", r_pid);
			psignal(WTERMSIG(status), "signal");
		}
	}
	else	if (errno != ECHILD)
		fprintf(stderr, "waitpid error: %s\n", 
				strerror(errno));
	printf("foreground reaped pid=%d, ready to return\n", r_pid);
	return;
}
Пример #6
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 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 pid = 1;
	int status ;
	while( pid >0 ){
		pid=waitpid(-1,&status,WNOHANG|WUNTRACED);         

		if( pid > 0){
		    if(WIFEXITED(status)){ // child exited normally
                //printf( "killed job [%d] , PID: %d with SIGINT \n", getjobpid(jobs, pid)->jid, getjobpid(jobs, pid)->pid );		    	
	            deletejob(jobs,pid);
            }
	         //child caught signal!!
	        if(WIFSIGNALED(status)){ 
                    printf( "killed job [%d] , PID: %d with SIGINT \n", getjobpid(jobs, pid)->jid, getjobpid(jobs, pid)->pid );
					deletejob(jobs,pid); // cntrl c so delete the job after kill is called
            }

	        if(WIFSTOPPED(status)){
                    printf( "stopped job [%d] , PID: %d with SIGTSTP\n", getjobpid(jobs, pid)->jid, getjobpid(jobs, pid)->pid );
					getjobpid(jobs, pid)->state=ST; // cntrl z so set the state to stop after kill is called
            }
        }
    }
	

}
Пример #7
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 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)
{
    // Save current errno value
    int tempErrNo = errno;
    int status = 0;
    pid_t pid;
    if ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) {
        if (WIFEXITED(status)) {
            deletejob(jobs, pid);
        }
        else if (WIFSIGNALED(status)) {
            // Get the terminated job
            struct job_t* myJob = getjobpid(jobs, pid);
            // Print info on therminated job
            safe_printf("Job [%d] (%d) terminated by signal %d\n", myJob->jid, myJob->pid, WTERMSIG(status));
            deletejob(jobs, pid);
        }
        else if (WIFSTOPPED(status)) {
            // Get the stopped job
            struct job_t* myJob = getjobpid(jobs, pid);
            // Change the state to stopped
            myJob->state = ST;
            // Print info on stopped job
            safe_printf("Job [%d] (%d) stopped by signal %d\n", myJob->jid, myJob->pid, WSTOPSIG(status));
        }
    }
    else {
        if (errno != 0) {
            unix_error("Waitpid error");
        }
    }
    // Restore errno value
    errno = tempErrNo;
    return;
}
Пример #8
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 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) 
{
	pid_t pid;
	int status;
	while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0)
	{
		if(WIFSIGNALED(status))
		{
			struct job_t* tempjob;
			if((tempjob=getjobpid(jobs,pid))!=NULL)
			{
				printf("Job [%d] (%d) terminated by signal %d\n",tempjob->jid,tempjob->pid,WTERMSIG(status));
				deletejob(jobs,pid);
			}
			continue;
		}
		if(WIFSTOPPED(status))
		{
			struct job_t* tempjob;
			if((tempjob=getjobpid(jobs,pid))!=NULL)
			{
				if(tempjob->state!=ST)
				{
					printf("Job [%d] (%d) stopped by signal %d\n",tempjob->jid,tempjob->pid,SIGTSTP);
					tempjob->state=ST;
				}
			}
			continue;
		}
		deletejob(jobs,pid);
	}
	
    return;
}
Пример #9
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 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)
{
    struct job_t *jd;
    pid_t pid;

    int status = -1;

    //returns 0 if working correctly, and will return -1 if it errors out
    while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0){
      jd = getjobpid(jobs, pid);

      if(WIFEXITED(status)){
        deletejob(jobs, pid);
      }

      if(WIFSIGNALED(status)){
        printf("[%d] (%d) terminated by signal 2\n",jd->jid, pid);
        deletejob(jobs, pid);
      }

      if(WIFSTOPPED(status)){
        printf("[%d] (%d) terminated by signal 20\n",jd->jid, pid);
        jd->state = ST;
      }

    }

    return;
}
Пример #10
0
void sigchld_handler(int sig) {
	pid_t pid;
	int status;
	struct job *p;
	if ((pid = waitpid(-1, &status, WUNTRACED)) > 0) {
		if (pid == forepid) 
			forepid = 0;
		if (WIFEXITED(status))
			deletejob(pid);
		else if (WIFSTOPPED(status)) {
			p = selectjob(pid);
			p->state = 0;
			fprintf(stderr, "job [%d] %d stopped by signal: Stopped\n",
					p->jid, pid);
		}
		else if (WIFSIGNALED(status)) {
			deletejob(pid);
			fprintf(stderr, "job %d terminated by ", pid);
			psignal(WTERMSIG(status), "signal");
		}
	}
	else if (errno != ECHILD)
		fprintf(stderr, "\nwaitpid error: %s\n", strerror(errno));
	return;
}
Пример #11
0
void fg_waitpid(pid_t pid) {
	int status;
	pid_t r_pid = 0;
	struct job *p = NULL;

	if ((r_pid = waitpid(pid, &status, 0)) > 0) {
		forepid = 0;
		if (WIFEXITED(status)) 
			deletejob(r_pid);
		else	if (WIFSTOPPED(status)) {
			p = selectjob(r_pid);
			p->state = 0;
			fprintf(stderr, "job [%d] %d stopped by signal: Stopped\n", 
					p->jid, r_pid);
		}
		else	if (WIFSIGNALED(status)) {
			deletejob(r_pid);
			fprintf(stderr, "job %d terminated by ", r_pid);
			psignal(WTERMSIG(status), "signal");
		}
	}
	else if (errno != ECHILD)
		fprintf(stderr, "waitpid error: %s\n", 
				strerror(errno));
	return;
}
Пример #12
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 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) {
	pid_t pid;
	int status;
	// Reap all the child process.
	while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
		//Handle with the 3 situation in this handler together.
		if (WIFSIGNALED(status)) {
			printf("Job [%d] (%d) terminated by Signal %d\n", pid2jid(pid),
					pid,
					WTERMSIG(status));
			deletejob(jobs, pid);
		} else if (
		WIFSTOPPED(status)) {
			struct job_t *job = getjobpid(jobs, pid);
			if (job == NULL) {
				printf("sigchld: Get job error.\n");
				return;
			}
			job->state = ST;
			printf("Job [%d] (%d) stopped by Signal %d\n", pid2jid(pid), pid,
			WEXITSTATUS(status));

		} else if (
		WIFEXITED(status)) {
			deletejob(jobs, pid);
		}

		//printf("Handler reaped child %d\n", (int)pid);
	}
	return;
}
Пример #13
0
Файл: tsh.c Проект: sanha/SP2015
/*
 * 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 status;
	if (verbose) printf ("sigchld_handler: entering\n");

	/* wait until some child is terminated */
	pid_t pid_ch, jid_ch ;
	while ((pid_ch = waitpid (-1, &status, WUNTRACED | WNOHANG)) > 0) {	// wait any terminated child
	    	jid_ch = pid2jid (pid_ch);
	    	if (verbose) printf ("sigchld_handler: Job [%d] (%d) deleted\n", jid_ch, pid_ch);
		if (WIFEXITED (status)) {		// case 1: child process terminated normally
			if (verbose) printf ("sigchld_handler: Job [%d] (%d) terminates OK (status 0)\n", jid_ch, pid_ch);
			deletejob (jobs, pid_ch);
		}
		else if (WIFSIGNALED (status)) {	// case 2: child process terminated via a signal that was not caught
			deletejob (jobs, pid_ch);
			printf ("Job [%d] (%d) terminated by signal %d\n", jid_ch, pid_ch, WTERMSIG (status));	
		}
		else if (WIFSTOPPED (status)) {		// case 3: child process stopped
		    	struct job_t *stopped = getjobpid (jobs, pid_ch);
			stopped->state = ST;

			printf ("Job [%d] (%d) stopped by signal %d\n", jid_ch, pid_ch, WSTOPSIG (status));
		}

	}

	if (verbose) printf ("sigchld_handler: exiting\n");

	return;
}
Пример #14
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 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 status;  
    pid_t pid;  
    
    while ((pid = waitpid(fgpid(jobs), &status, WNOHANG|WUNTRACED)) > 0) {  
        if (WIFSTOPPED(status)){ 
            //change state if stopped
            getjobpid(jobs, pid)->state = ST;
            int jid = pid2jid(pid);
            printf("Job [%d] (%d) Stopped by signal %d\n", jid, pid, WSTOPSIG(status));
        }  
        else if (WIFSIGNALED(status)){
            //delete is signaled
            int jid = pid2jid(pid);  
            printf("Job [%d] (%d) terminated by signal %d\n", jid, pid, WTERMSIG(status));
            deletejob(jobs, pid);
        }  
        else if (WIFEXITED(status)){  
            //exited
            deletejob(jobs, pid);  
        }  
    }  
    return; 
}
Пример #15
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 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) 
{
        //Throw out finished processes
    //Change status to ST for stopped processes

    int child_status;
    
    pid_t culprit_pid; //pid of terminated or stopped child, 0 if no child terminated/stopped, -1 err
    pid_t culprit_jid;

    
    while((culprit_pid = waitpid(-1, &child_status, WNOHANG | WUNTRACED)) > 0)
    {
        culprit_jid = pid2jid(culprit_pid);
        
        if (WIFEXITED(child_status))
        {
            //Child terminated normally, via a call to exit or a return
            if (verbose)    
                printf("child %d exited normally\n", culprit_pid);

            deletejob(jobs, culprit_pid);   
        }

        else if (WIFSIGNALED(child_status))
        {
            //Child terminated because of a signal that was not caught
            
            if (verbose)
                printf("child %d exited because of a signal\n", culprit_pid);

            deletejob(jobs, culprit_pid);
            
            printf("Job [%d] (%d) terminated by signal %d", culprit_jid, culprit_pid, WTERMSIG(child_status));
            printf("\n");
        }
    
        else if (WIFSTOPPED(child_status))
        {
            //Child that caused the return is stopped

            if (verbose)
                printf("child %d stopped\n", culprit_pid);
            
            //Change job list state to stopped
            struct job_t *myJob = getjobpid(jobs, culprit_pid);
            myJob->state = ST;
            
            printf("Job [%d] (%d) stopped by signal %d", culprit_jid, culprit_pid, WSTOPSIG(child_status));
            printf("\n");
        }
        
        
    }
}
Пример #16
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) {

    int status;
    pid_t pid;
    int olderrno = errno; // store errno in handler

    /*
     * Reap child with the pid if the child is stopped or terminated
     * If a child is terminated normally, delete the child from the job list
     * If a child is stopped by a signal, set the job status as stopped
     * If a child is terminated by a signal that was not caught, delete the child from the job list
     */
    while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) {

        if (WIFEXITED(status)) {

            deletejob(job_list, pid); // the child ternimated normally

        } else if (WIFSTOPPED(status)) {

            /*
             * Avoid printf() in handler, use helper function to write the output to stdout
             */
            sio_puts("Job [");
            sio_putl(pid2jid(pid));
            sio_puts("] (");
            sio_putl(pid);
            sio_puts(") stopped by signal ");
            sio_putl(WSTOPSIG(status));
            sio_puts("\n");

            getjobpid(job_list, pid) -> state = ST; // the child was stopped by a signal 

        } else if (WIFSIGNALED(status)) { // the child was terminated by a signal that was not caught

            /*
             * Avoid printf() in handler, use helper function to write the output to stdout
             */
            sio_puts("Job [");
            sio_putl(pid2jid(pid));
            sio_puts("] (");
            sio_putl(pid);
            sio_puts(") terminated by signal ");
            sio_putl(WTERMSIG(status));
            sio_puts("\n");

			deletejob(job_list, pid);

        }

    }

    errno = olderrno;
    return;
}
Пример #17
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 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 child_status;	// child process status for waitpid
	pid_t wpid;
	struct job_t *job;

	// wait for child process while there is any child left
	while(maxjid(jobs))
	{
		// -1			: wait for any child
		// WNOHANG		: don't block procedure
		// WUNTRACED	: trace stopped child
		wpid = waitpid(-1, &child_status, WNOHANG | WUNTRACED);

		if(wpid == -1)
		{
			// handle waitpid error
			perror("waitpid");
			return;
		}
		else if(wpid == 0)
		{
			// no child was terminated or stopped
			break;
		}

		// find job object with pid
		// getjobpid never fails
		job = getjobpid(jobs, wpid);

		// check child status
		if(WIFSIGNALED(child_status))
		{
			// child terminated by a signal
			printf("Job [%d] (%d) terminated by signal %d\n", job->jid, job->pid, WTERMSIG(child_status));
			// delete job from job list
			deletejob(jobs, wpid);
		}
		else if(WIFSTOPPED(child_status))
		{
			// child stopped
			printf("Job [%d] (%d) stopped by signal %d\n", job->jid, job->pid, WSTOPSIG(child_status));
			// set state
			job->state = ST;
		}
		else if(WIFEXITED(child_status))
		{
			// child exited properly
			// delete job from job list
			deletejob(jobs, wpid);
		}
	}
}
Пример #18
0
void sigchld_handler(int sig) {
	pid_t pid;
	int status;
	struct job *p;
	if ((pid = waitpid(-1, &status, WUNTRACED)) > 0) {
		if (WIFEXITED(status)) {
			deletejob(pid);
			if (pid == forepid) {
				forepid = 0;
				setpgid(pid, pid);
				fprintf(stderr, "foreground job %d terminated normally with exit status=%d\n",
						pid, WEXITSTATUS(status));
				siglongjmp(env, 1);
			}
			else
				fprintf(stderr, "job %d terminated normally with exit status=%d\n",
						pid, WEXITSTATUS(status));
		}
		else if (WIFSTOPPED(status)) {
			p = selectjob(pid);
			p->state = 0;
			if (pid == forepid) {
				forepid = 0;
				setpgid(pid, pid);
				fprintf(stderr, "foreground job [%d] %d stopped by signal: Stopped\n",
						p->jid, pid);
				siglongjmp(env, 1);
			}
			else
				fprintf(stderr, "job [%d] %d stopped by signal: Stopped\n",
						p->jid, pid);
		}
		else if (WIFSIGNALED(status)) {
			deletejob(pid);
			if (pid == forepid) {
				forepid = 0;
				setpgid(pid, pid);
				fprintf(stderr, "foreground job %d terminated by ", pid);
				psignal(WTERMSIG(status), "signal");
				siglongjmp(env, 1);
			}
			else
			fprintf(stderr, "job %d terminated by ", pid);
			psignal(WTERMSIG(status), "signal");
		}
	}
	else if (errno != ECHILD)
		fprintf(stderr, "waitpid error: %s\n", strerror(errno));
	printf("handler reaped pid=%d, ready to return right now.\n", pid);
	return;
}
Пример #19
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 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 status;         // Status
    pid_t pid;          // pid
    struct job_t *pjob; // Pointer to job

    do {
    // Following directions from the link in the README
        pid = waitpid(-1, &status, WNOHANG|WUNTRACED); // Using WNOHANG as spoken about in class
        if (pid > 0) {
            if (WIFSTOPPED(status)) {
            // If stopped
                if ((pjob = getjobpid(jobs, pid)) != NULL) {
                // get job and change state
                    pjob->state = ST; // changing state
                    printf("Job [%d] (%d) stopped by signal 20\n", pjob->jid, pjob->pid);
                } else {
                // Job was invalid
                    printf("sigchld_handler: getjobpid error\n");
                    exit(1);
                }
            } else if (WIFSIGNALED(status)) {
                // TODO: Find the link for the second tutorial
                if ((pjob = getjobpid(jobs, pid)) != NULL) {
                    printf("Job [%d] (%d) terminated by signal 2\n", pjob->jid, pjob->pid);
                    if (!deletejob(jobs, pid)) { // Delete job
                        printf("sigchld_handler: deletejob error\n");
                        exit(1);
                    }
                } else {
                    printf("sigchld_handler: getjobpid error\n");
                    exit(1);
                }
            } else if (WIFEXITED(status)) {
                if (!deletejob(jobs, pid)) {
                    // DELETE JOB
                    printf("sigchld_handler: deletejob error\n");
                    exit(1);
                }
            } else {
                printf("Unknown waitpid\n");
                exit(1);
            }
        } else if (pid == -1 && errno == EINTR) {
            continue;
        } else {
            break;
        }
    } while (1);
    return;
}
Пример #20
0
/* 
 * builtin_cmd - If the user has typed a built-in command then execute
 *    it immediately.  
 */
int builtin_cmd(char **argv) 
{
	int r=0;
	char* p;
        int jobid;
   	if(strcmp(argv[0],"quit")==0)
	{
		r++;
		exit(0);
	}
	else if(strcmp(argv[0],"jobs")==0)
        {
	 	r++;
	        listjobs(jobs);
	}
	else if((strcmp(argv[0],"bg")==0)||(strcmp(argv[0],"fg")==0))
        {
		r++;
		do_bgfg(argv);
	}
	else if(strcmp(argv[0],"kill")==0)
	{
        	r++;
                p = strstr(argv[1],"%");
                p++;
                jobid=atoi(p);     //Since jobid is specified as %5 for job 5 we get 5 from argv[1].
                jobid=getjobjid(jobs,jobid)->pid;
                kill(jobid,SIGKILL);
                deletejob(jobs,jobid);
	}
return r;     /* not a builtin command */
}
Пример #21
0
// delete delayed jobs
void datacloud::deletedelayedjobs()
   {
   jobqueueelem *job,*prev;

   BOOLINT flag;

   job=JOBQUEUETAIL;

   while (job!=NULL)
      {
      flag=FALSE;

      if (job->hfield!=NULL)
         if (job->hfield->isdelayed) flag=TRUE;

      if (job->texture!=NULL)
         if (job->texture->isdelayed) flag=TRUE;

      if (job->fogmap!=NULL)
         if (job->fogmap->isdelayed) flag=TRUE;

      prev=job->prev;

      if (flag) deletejob(job);

      job=prev;
      }
   }
Пример #22
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 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)
{
	// Jung driving now

	int status;
	pid_t pid;
	struct job_t *job;
	const int STDOUT = 1;
	/* check either status of children or return if no child zombied */
	while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) {

		job = getjobpid(jobs, pid);

		if (WIFSTOPPED(status)) { /* stopped or ctrl+z */
			job->state = ST;
			char buffer[100];
			sprintf(buffer, "Job [%d] (%d) stopped by signal %d\n", job->jid, job->pid, WSTOPSIG(status));
			write(STDOUT, buffer, strlen(buffer));
		} 
		else {
			if (WIFSIGNALED(status)) { /* terminated or ctrl+c */
				char buffer[100];
				sprintf(buffer, "Job [%d] (%d) terminated by signal %d\n", job->jid, job->pid, WTERMSIG(status));
				write(STDOUT, buffer, strlen(buffer));
			}
			deletejob(jobs, pid); /* delete job in all other cases */
		}
	}
	return;

	// end of Jung driving, Kyung driving now
}
Пример #23
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 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)
{
#ifdef DEBUG_SIGTSTP
    printf("--------------SIGCHLD-----------------\n");
    listjobs(jobs);
fflush(stdout);
#endif
    pid_t pid;
    int status;
    while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0){
#ifdef DEBUG_SIGTSTP
    printf("pid = %d\n", pid);
    printf("WIFEXITED(status) = %d\n",WIFEXITED(status));
#endif
        if(WIFSTOPPED(status)){
            getjobpid(jobs, pid)->state = ST;
            continue;
        }
        deletejob(jobs, pid);
    }
#ifdef DEBUG_SIGTSTP
    printf("pid=%d\n",pid);
    listjobs(jobs);
    printf("---------------------------------------\n");
    fflush(stdout);
#endif
    return;
}
Пример #24
0
/* 
 * waitfg - block until FG job pid terminates or stops.
 */
void waitfg(pid_t pid)
{
    int status;
    
    /* wait for FG job to stop (WUNTRACED) or terminate */
    if (waitpid(pid, &status, WUNTRACED) < 0)
	unix_error("waitfg: waitpid error");
    
    /* FG job has stopped. Change its state in jobs list */
    if (WIFSTOPPED(status)) {
	sprintf(sbuf, "Job %d stopped by signal", pid);
	psignal(WSTOPSIG(status), sbuf); 
	updatejob(jobs, pid, ST);
    }
    
    /* FG job has terminated. Remove it from job list */
    else {
	/* check if job was terminated by an uncaught signal */
	if (WIFSIGNALED(status)) { 
	    sprintf(sbuf, "Job %d terminated by signal", pid);
	    psignal(WTERMSIG(status), sbuf); 
	}
	deletejob(jobs, pid);
	if (verbose)
	    printf("waitfg: job %d deleted\n", pid);
    }
}
Пример #25
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 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 info; 
    pid_t pid;


    while ((pid = waitpid(fgpid(jobs), &info, WNOHANG|WUNTRACED)) > 0) {

        if (WIFSTOPPED(info))  // Job exited by external process
        { 
            sigtstp_handler(20);
        } 
        else if (WIFSIGNALED(info)) // job terminated due to faulty signal
        {
            sigint_handler(-2);
        } 
        else if (WIFEXITED(info)) // Job exits normalls

        { 
            deletejob(jobs, pid);
        }
    }

   
    if ((errno != ECHILD && pid == -1) || pid > 0) // After the loop pid is -1, or pid is 0
    { 
        unix_error("WAITPID ERROR 404");
    }
    return;
}
Пример #26
0
/* 
 * builtin_cmd - If the user has typed a built-in command then execute
 *    it immediately.  
 */
int builtin_cmd(char **argv) 
{
    if (!strcmp(argv[0], "quit"))
    {
        exit(0);
    }
    if (!strcmp(argv[0], "jobs"))
    {
        listjobs(jobs);
        return 1;
    }
    if ((!strcmp(argv[0], "bg") || !strcmp(argv[0], "fg")) && (argv[1] != NULL))
    {
        do_bgfg(argv);
        return 1;
    }
    if (!strcmp(argv[0], "kill"))
    {
        pid_t pid = atoi(argv[1]);
        kill(-pid, SIGKILL);
        if (getjobpid(jobs, pid) != NULL) 
        {
            if (waitpid(pid, NULL, 0) < 0)
                unix_error("kill child process error");
            deletejob(jobs, pid);
        }
        return 1;
    }
    return 0;     /* not a builtin command */
}
Пример #27
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 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)
{
        pid_t pid;
        int status;
        while (( pid = waitpid(-1,&status, WNOHANG | WUNTRACED)) > 0) // reaping whatever is ready no hang
        {
					if(WIFSTOPPED(status) )
					{
						if((getjobpid(jobs,pid)->state) != ST)
						{
							 printf("Job [%d] (%d) Stopped by Signal %d\n",(getjobpid(jobs,pid))->jid, pid, SIGTSTP);

						}
						 getjobpid(jobs, pid)->state = ST;
						 return;
					 }
						else if(WIFSIGNALED(status) && fgpid(jobs) ==pid )
						{
							if(pid != 0){ printf("Job [%d] (%d) Terminated by Signal %d\n",(getjobpid(jobs,pid))->jid, pid, SIGINT);
}
							kill(-pid,SIGINT);
						}
                deletejob(jobs, pid);
        }


        return;
}
Пример #28
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 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)
{
    /* reaps all zombie and doesn't block */
    pid_t reap_pid;
    int state = 0;  /* used to determine what causes the SIGCHLD */
    /* waitpid() return 0 immediately when no childs have terminated */
    while (0 < (reap_pid = waitpid(-1, &state, WNOHANG))) {
        /* DBG(("reaped child %d", (int)reap_pid)); */
        /*TODO Is it safe to call getjobpid(), deletejob(), clearjob() in the signal handler?  */
        if (WIFSIGNALED(state)) {
            struct job_t *termjob = getjobpid(jobs, reap_pid);
            fprintf(stdout, "hello Job [%d] (%d) terminated by signal %d\n", termjob->jid, termjob->pid, WTERMSIG(state));
        }
        deletejob(jobs, reap_pid);
        clearjob(getjobpid(jobs, reap_pid));
    }

    if (-1 == reap_pid && errno != ECHILD)
        unix_error("waitpid()");

    /* if a job be suspended, we need to change its state here */
    pid_t stp_pid;
    /* waitpid return 0 if there is no terminated process and stopped process */
    while (0 < (stp_pid = waitpid(-1, &state, WNOHANG | WUNTRACED))) {
        struct job_t *stpjob = getjobpid(jobs, stp_pid);
        stpjob->state = ST;
        if (WIFSTOPPED(state)) {
            fprintf(stdout, "world Job [%d] (%d) stopped by signal %d\n", stpjob->jid, stpjob->pid, WSTOPSIG(state));
        }
    }

    if (-1 == stp_pid && errno != ECHILD)
        unix_error("waitpid()");
}
Пример #29
0
/* $begin procmask */
void handler(int sig)
{
    pid_t pid;
    while ((pid = waitpid(-1, NULL, 0)) > 0) /* Reap a zombie child */
	deletejob(pid); /* Delete the child from the job list */
    if (errno != ECHILD)
	unix_error("waitpid error");
}
Пример #30
0
Файл: tsh.c Проект: GAONNR/CS230
/*
 * 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)
{
	if(verbose)
		printf("sigchld_handler: entering\n");
	int status;
	pid_t pid;
	pid = waitpid(-1,&status,WNOHANG | WUNTRACED);
	if(!pid) return;
	struct job_t *job = getjobpid(jobs,pid);
	//if child was killed by signal
	if(WIFSIGNALED(status))
	{
		kill(-pid, SIGKILL);
		if(verbose)
		{
			printf("sigchld_handler: Job [%d] (%d) deleted\n", job->jid, pid);
		}
		printf("Job [%d] (%d) terminated by signal %d\n", job->jid, pid, WTERMSIG(status));


		deletejob(jobs,pid);
	}
	//if child is stopped
	else if(WIFSTOPPED(status))
	{
		job->state = ST;

		printf("Job [%d] (%d) stopped by signal %d\n", job->jid,pid,WSTOPSIG(status));

	}
	//if child was killed normaly
	else if(WIFEXITED(status))
	{
		kill(-pid, SIGKILL);
		if(verbose){
			printf("sigchld_handler: Job [%d] (%d) deleted\n", job->jid, pid);
			printf("sigchld_handler: Job [%d] (%d) terminates OK (status %d)\n",
				job->jid, pid, WEXITSTATUS(status));
		}
		deletejob(jobs,pid);
	}
	if(verbose)
	printf("sigchld_handler: exiting\n");
    return;
}