示例#1
0
文件: dns.c 项目: Cougar/dircproxy
/* Called to end a DNS request.  0 = Not handled, >0 = Ok, <0 = Error */
int dns_endrequest(pid_t pid, int status) {
  struct dnschild *lastchild, *child;
  struct dnsresult result;
  char *ip;
  char *name;
  size_t len;

  /* Check to see whether this was a DNS child */
  child = dnschildren;
  lastchild = 0;
  while (child) {
    if (child->pid == pid)
      break;

    lastchild = child;
    child = child->next;
  }
  if (!child)
    return 0;

  /* Remove it from the list */
  if (lastchild) {
    lastchild->next = child->next;
  } else {
    dnschildren = child->next;
  }

  debug("%d: Was a DNS child, getting result", pid);

  /* Parameters to call function with */
  name = 0;
  ip = 0;
  
  /* Read from pipe if child returned normally */
  if (WIFEXITED(status)) {
    if (!WEXITSTATUS(status)) {
      len = read(child->pipe, (void *)&result, sizeof(struct dnsresult));
      if (len != sizeof(struct dnsresult)) {
        syscall_fail("read", 0, 0);
      } else if (result.success) {
        debug("%d: Got result", pid);

        ip = result.ip;
        name = result.name;
      } else {
        debug("%d: DNS lookup failed", pid);
      }
    } else {
      debug("%d: DNS lookup returned %d", pid, WEXITSTATUS(status));
    }
  } else if (WIFSIGNALED(status)) {
    debug("%d: DNS lookup terminated with signal %d", pid, WTERMSIG(status));
  } else {
    debug("%d: DNS lookup terminated abnormally", pid);
  }

  /* If DNS failed, but we were looking up an IP address, fill that */
  if (!ip && child->ip) {
    strcpy(result.ip, child->ip);
    ip = result.ip;
  }

  /* If DNS failed but we have an IP, fill the name with the IP */
  if (ip && (!name || !strlen(name))) {
    strncpy(result.name, ip, sizeof(result.name));
    result.name[sizeof(result.name) - 1] = '\0';

    debug("%d: Changed name to '%s'", pid, result.name);
    name = result.name;
  }

  /* Call the function */
  child->function(child->boundto, child->data, ip, name);

  /* Clean up */
  close(child->pipe);
  free(child);

  return 1;
}
示例#2
0
int job_reap( bool interactive )
{
    ASSERT_IS_MAIN_THREAD();
	job_t *jnext;	
	int found=0;
	
	static int locked = 0;
	
	locked++;	
	
	/*
	  job_read may fire an event handler, we do not want to call
	  ourselves recursively (to avoid infinite recursion).
	*/
	if( locked>1 )
		return 0;
    
    job_iterator_t jobs;
    jnext = jobs.next();
	while (jnext)
    {
        job_t *j = jnext;
        jnext = jobs.next();
		process_t *p;
		
		/*
		  If we are reaping only jobs who do not need status messages
		  sent to the console, do not consider reaping jobs that need
		  status messages
		*/
		if( (!job_get_flag( j, JOB_SKIP_NOTIFICATION ) ) && (!interactive) && (!job_get_flag( j, JOB_FOREGROUND )))
		{
			continue;
		}
	
		for( p=j->first_process; p; p=p->next )
		{
			int s;
			if( !p->completed )
				continue;
			
			if( !p->pid )
				continue;			
			
			s = p->status;
			
			proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );			
			
			if( WIFSIGNALED(s) )
			{
				/* 
				   Ignore signal SIGPIPE.We issue it ourselves to the pipe
				   writer when the pipe reader dies.
				*/
				if( WTERMSIG(s) != SIGPIPE )
				{	
					int proc_is_job = ((p==j->first_process) && (p->next == 0));
					if( proc_is_job )
						job_set_flag( j, JOB_NOTIFIED, 1 );
					if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
					{
						if( proc_is_job )
							fwprintf( stdout,
									  _( L"%ls: Job %d, \'%ls\' terminated by signal %ls (%ls)" ),
									  program_name,
									  j->job_id, 
									  j->command_wcstr(),
									  sig2wcs(WTERMSIG(p->status)),
									  signal_get_desc( WTERMSIG(p->status) ) );
						else
							fwprintf( stdout,
									  _( L"%ls: Process %d, \'%ls\' from job %d, \'%ls\' terminated by signal %ls (%ls)" ),
									  program_name,
									  p->pid,
									  p->argv0(),
									  j->job_id,
									  j->command_wcstr(),
									  sig2wcs(WTERMSIG(p->status)),
									  signal_get_desc( WTERMSIG(p->status) ) );
						tputs(clr_eol,1,&writeb);
						fwprintf (stdout, L"\n" );
						found=1;						
					}
					
					/* 
					   Clear status so it is not reported more than once
					*/
					p->status = 0;
				}
			}						
		}
		
		/* 
		   If all processes have completed, tell the user the job has
		   completed and delete it from the active job list.  
		*/
		if( job_is_completed( j ) ) 
		{
			if( !job_get_flag( j, JOB_FOREGROUND) && !job_get_flag( j, JOB_NOTIFIED ) && !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
			{
				format_job_info( j, _( L"ended" ) );
				found=1;
			}
			proc_fire_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 );			
			proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );			

			job_free(j);
		}		
		else if( job_is_stopped( j ) && !job_get_flag( j, JOB_NOTIFIED ) ) 
		{
			/* 
			   Notify the user about newly stopped jobs. 
			*/
			if( !job_get_flag( j, JOB_SKIP_NOTIFICATION ) )
			{
				format_job_info( j, _( L"stopped" ) );
				found=1;
			}			
			job_set_flag( j, JOB_NOTIFIED, 1 );
		}
	}

	if( found )
		fflush( stdout );

	locked = 0;
	
	return found;	
}
示例#3
0
extern "C" int32_t WIfSignaled(int32_t status)
{
    return WIFSIGNALED(status);
}
示例#4
0
文件: unix.c 项目: dnaeon/core
int Unix_ShellCommandReturnsZero(char *comm, int useshell)
{
    int status;
    pid_t pid;

    if (!useshell)
    {
        /* Build argument array */

    }

    if ((pid = fork()) < 0)
    {
        FatalError("Failed to fork new process");
    }
    else if (pid == 0)          /* child */
    {
        ALARM_PID = -1;

        if (useshell)
        {
            if (execl(SHELL_PATH, "sh", "-c", comm, NULL) == -1)
            {
                CfOut(cf_error, "execl", "Command %s failed", comm);
                exit(1);
            }
        }
        else
        {
            char **argv = ArgSplitCommand(comm);

            if (execv(argv[0], argv) == -1)
            {
                CfOut(cf_error, "execv", "Command %s failed", argv[0]);
                exit(1);
            }
        }
    }
    else                        /* parent */
    {
# ifndef HAVE_WAITPID
        pid_t wait_result;
# endif
        ALARM_PID = pid;

# ifdef HAVE_WAITPID

        while (waitpid(pid, &status, 0) < 0)
        {
            if (errno != EINTR)
            {
                return -1;
            }
        }

        return (WEXITSTATUS(status) == 0);

# else

        while ((wait_result = wait(&status)) != pid)
        {
            if (wait_result <= 0)
            {
                CfOut(cf_inform, "wait", " !! Wait for child failed\n");
                return false;
            }
        }

        if (WIFSIGNALED(status))
        {
            return false;
        }

        if (!WIFEXITED(status))
        {
            return false;
        }

        return (WEXITSTATUS(status) == 0);
# endif
    }

    return false;
}
示例#5
0
void job_continue (job_t *j, int cont)
{
	/*
	  Put job first in the job list
	*/
    job_promote(j);
	job_set_flag( j, JOB_NOTIFIED, 0 );

	CHECK_BLOCK();
	
	debug( 4,
		   L"Continue job %d, gid %d (%ls), %ls, %ls",
		   j->job_id, 
		   j->pgid,
		   j->command_wcstr(), 
		   job_is_completed( j )?L"COMPLETED":L"UNCOMPLETED", 
		   is_interactive?L"INTERACTIVE":L"NON-INTERACTIVE" );
	
	if( !job_is_completed( j ) )
	{
		if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
		{							
			/* Put the job into the foreground.  */
			int ok;
			
			signal_block();
			
			ok = terminal_give_to_job( j, cont );
			
			signal_unblock();		

			if( !ok )
				return;
			
		}
		
		/* 
		   Send the job a continue signal, if necessary.  
		*/
		if( cont )
		{
			process_t *p;

			for( p=j->first_process; p; p=p->next )
				p->stopped=0;

			if( job_get_flag( j, JOB_CONTROL ) )
			{
				if( killpg( j->pgid, SIGCONT ) )
				{
					wperror( L"killpg (SIGCONT)" );
					return;
				}
			}
			else
			{
				for( p=j->first_process; p; p=p->next )
				{
					if (kill ( p->pid, SIGCONT) < 0)
					{
						wperror (L"kill (SIGCONT)");
						return;
					}		
				}
			}
		}
	
		if( job_get_flag( j, JOB_FOREGROUND ) )
		{
			int quit = 0;
		
			/* 
			   Wait for job to report. Looks a bit ugly because it has to
			   handle the possibility that a signal is dispatched while
			   running job_is_stopped().
			*/
			while( !quit )
			{
				do
				{
					got_signal = 0;
					quit = job_is_stopped( j ) || job_is_completed( j );
				}
				while (got_signal && !quit);
                
				if( !quit )
				{
					
//					debug( 1, L"select_try()" );	
					switch( select_try(j) )
					{
						case 1:			
						{
							read_try( j );
							break;
						}
					
						case -1:
						{
							/*
							  If there is no funky IO magic, we can use
							  waitpid instead of handling child deaths
							  through signals. This gives a rather large
							  speed boost (A factor 3 startup time
							  improvement on my 300 MHz machine) on
							  short-lived jobs.
							*/
							int status;						
							pid_t pid = waitpid(-1, &status, WUNTRACED );
							if( pid > 0 )
							{
								handle_child_status( pid, status );
							}
							else
							{
								/*
								  This probably means we got a
								  signal. A signal might mean that the
								  terminal emulator sent us a hup
								  signal to tell is to close. If so,
								  we should exit.
								*/
								if( reader_exit_forced() )
								{
									quit = 1;
								}
								
							}
							break;
						}
								
					}
				}					
			}
		}	
	}
	
	if( job_get_flag( j, JOB_FOREGROUND ) )
	{
		
		if( job_is_completed( j ))
		{
        
			// It's possible that the job will produce output and exit before we've even read from it.
			// We'll eventually read the output, but it may be after we've executed subsequent calls
			// This is why my prompt colors kept getting screwed up - the builtin echo calls
			// were sometimes having their output combined with the set_color calls in the wrong order!
			read_try(j);

        
			process_t *p = j->first_process;
			while( p->next )
				p = p->next;

			if( WIFEXITED( p->status ) || WIFSIGNALED(p->status))
			{
				/* 
				   Mark process status only if we are in the foreground
				   and the last process in a pipe, and it is not a short circuted builtin
				*/
				if( p->pid )
				{
					int status = proc_format_status(p->status);
					//wprintf(L"setting status %d for %ls\n", job_get_flag( j, JOB_NEGATE )?!status:status, j->command);
					proc_set_last_status( job_get_flag( j, JOB_NEGATE )?!status:status);
				}
			}			
		}
		/* 
		   Put the shell back in the foreground.  
		*/
		if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
		{
			int ok;
			
			signal_block();

			ok = terminal_return_from_job( j );
			
			signal_unblock();
			
			if( !ok )
				return;
			
		}
	}
	
}
示例#6
0
/* Wait for a subprocess to finish.  Return its exit code.
   If it didn't terminate correctly, exit if exit_on_error is true, otherwise
   return 127.  */
int
wait_subprocess (pid_t child, const char *progname,
                 bool ignore_sigpipe, bool null_stderr,
                 bool slave_process, bool exit_on_error,
                 int *termsigp)
{
#if HAVE_WAITID && defined WNOWAIT && 0
  /* Commented out because waitid() without WEXITED and with WNOWAIT doesn't
     work: On Solaris 7 and OSF/1 4.0, it returns -1 and sets errno = ECHILD,
     and on HP-UX 10.20 it just hangs.  */
  /* Use of waitid() with WNOWAIT avoids a race condition: If slave_process is
     true, and this process sleeps a very long time between the return from
     waitpid() and the execution of unregister_slave_subprocess(), and
     meanwhile another process acquires the same PID as child, and then - still
     before unregister_slave_subprocess() - this process gets a fatal signal,
     it would kill the other totally unrelated process.  */
  siginfo_t info;

  if (termsigp != NULL)
    *termsigp = 0;
  for (;;)
    {
      if (waitid (P_PID, child, &info, WEXITED | (slave_process ? WNOWAIT : 0))
          < 0)
        {
# ifdef EINTR
          if (errno == EINTR)
            continue;
# endif
          if (exit_on_error || !null_stderr)
            error (exit_on_error ? EXIT_FAILURE : 0, errno,
                   _("%s subprocess"), progname);
          return 127;
        }

      /* info.si_code is set to one of CLD_EXITED, CLD_KILLED, CLD_DUMPED,
         CLD_TRAPPED, CLD_STOPPED, CLD_CONTINUED.  Loop until the program
         terminates.  */
      if (info.si_code == CLD_EXITED
          || info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED)
        break;
    }

  /* The child process has exited or was signalled.  */

  if (slave_process)
    {
      /* Unregister the child from the list of slave subprocesses, so that
         later, when we exit, we don't kill a totally unrelated process which
         may have acquired the same pid.  */
      unregister_slave_subprocess (child);

      /* Now remove the zombie from the process list.  */
      for (;;)
        {
          if (waitid (P_PID, child, &info, WEXITED) < 0)
            {
# ifdef EINTR
              if (errno == EINTR)
                continue;
# endif
              if (exit_on_error || !null_stderr)
                error (exit_on_error ? EXIT_FAILURE : 0, errno,
                       _("%s subprocess"), progname);
              return 127;
            }
          break;
        }
    }

  switch (info.si_code)
    {
    case CLD_KILLED:
    case CLD_DUMPED:
      if (termsigp != NULL)
        *termsigp = info.si_status; /* TODO: or info.si_signo? */
# ifdef SIGPIPE
      if (info.si_status == SIGPIPE && ignore_sigpipe)
        return 0;
# endif
      if (exit_on_error || (!null_stderr && termsigp == NULL))
        error (exit_on_error ? EXIT_FAILURE : 0, 0,
               _("%s subprocess got fatal signal %d"),
               progname, info.si_status);
      return 127;
    case CLD_EXITED:
      if (info.si_status == 127)
        {
          if (exit_on_error || !null_stderr)
            error (exit_on_error ? EXIT_FAILURE : 0, 0,
                   _("%s subprocess failed"), progname);
          return 127;
        }
      return info.si_status;
    default:
      abort ();
    }
#else
  /* waitpid() is just as portable as wait() nowadays.  */
  int status;

  if (termsigp != NULL)
    *termsigp = 0;
  status = 0;
  for (;;)
    {
      int result = waitpid (child, &status, 0);

      if (result != child)
        {
# ifdef EINTR
          if (errno == EINTR)
            continue;
# endif
# if 0 /* defined ECHILD */
          if (errno == ECHILD)
            {
              /* Child process nonexistent?! Assume it terminated
                 successfully.  */
              status = 0;
              break;
            }
# endif
          if (exit_on_error || !null_stderr)
            error (exit_on_error ? EXIT_FAILURE : 0, errno,
                   _("%s subprocess"), progname);
          return 127;
        }

      /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status)
         must always be true, since we did not specify WCONTINUED in the
         waitpid() call.  Loop until the program terminates.  */
      if (!WIFSTOPPED (status))
        break;
    }

  /* The child process has exited or was signalled.  */

  if (slave_process)
    /* Unregister the child from the list of slave subprocesses, so that
       later, when we exit, we don't kill a totally unrelated process which
       may have acquired the same pid.  */
    unregister_slave_subprocess (child);

  if (WIFSIGNALED (status))
    {
      if (termsigp != NULL)
        *termsigp = WTERMSIG (status);
# ifdef SIGPIPE
      if (WTERMSIG (status) == SIGPIPE && ignore_sigpipe)
        return 0;
# endif
      if (exit_on_error || (!null_stderr && termsigp == NULL))
        error (exit_on_error ? EXIT_FAILURE : 0, 0,
               _("%s subprocess got fatal signal %d"),
               progname, (int) WTERMSIG (status));
      return 127;
    }
  if (!WIFEXITED (status))
    abort ();
  if (WEXITSTATUS (status) == 127)
    {
      if (exit_on_error || !null_stderr)
        error (exit_on_error ? EXIT_FAILURE : 0, 0,
               _("%s subprocess failed"), progname);
      return 127;
    }
  return WEXITSTATUS (status);
#endif
}
示例#7
0
extern int as_mysql_step_complete(mysql_conn_t *mysql_conn,
				  struct step_record *step_ptr)
{
	time_t now;
	int elapsed;
	int comp_status;
	int cpus = 0;
	struct jobacctinfo *jobacct = (struct jobacctinfo *)step_ptr->jobacct;
	struct jobacctinfo dummy_jobacct;
	double ave_vsize = 0, ave_rss = 0, ave_pages = 0;
	double ave_cpu = 0, ave_cpu2 = 0;
	char *query = NULL;
	int rc =SLURM_SUCCESS;
	uint32_t exit_code = 0;
	time_t start_time, submit_time;

	if (!step_ptr->job_ptr->db_index
	    && ((!step_ptr->job_ptr->details
		 || !step_ptr->job_ptr->details->submit_time)
		&& !step_ptr->job_ptr->resize_time)) {
		error("as_mysql_step_complete: "
		      "Not inputing this job, it has no submit time.");
		return SLURM_ERROR;
	}

	if (step_ptr->job_ptr->resize_time) {
		submit_time = start_time = step_ptr->job_ptr->resize_time;
		if (step_ptr->start_time > submit_time)
			start_time = step_ptr->start_time;
	} else {
		start_time = step_ptr->start_time;
		submit_time = step_ptr->job_ptr->details->submit_time;
	}

	if (jobacct == NULL) {
		/* JobAcctGather=slurmdb_gather/none, no data to process */
		memset(&dummy_jobacct, 0, sizeof(dummy_jobacct));
		jobacct = &dummy_jobacct;
	}

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (slurmdbd_conf) {
		now = step_ptr->job_ptr->end_time;
		cpus = step_ptr->cpu_count;
	} else if (step_ptr->step_id == SLURM_BATCH_SCRIPT) {
		now = time(NULL);
		cpus = 1;
	} else {
		now = time(NULL);
#ifdef HAVE_BG_L_P
		/* Only L and P use this code */
		cpus = step_ptr->job_ptr->details->min_cpus;
#else
		if (!step_ptr->step_layout || !step_ptr->step_layout->task_cnt)
			cpus = step_ptr->job_ptr->total_cpus;
		else
			cpus = step_ptr->cpu_count;
#endif
	}

	if ((elapsed = (now - start_time)) < 0)
		elapsed = 0;	/* For *very* short jobs, if clock is wrong */

	exit_code = step_ptr->exit_code;
	if (WIFSIGNALED(exit_code)) {
		comp_status = JOB_CANCELLED;
	} else if (exit_code)
		comp_status = JOB_FAILED;
	else {
		step_ptr->requid = -1;
		comp_status = JOB_COMPLETE;
	}

	/* figure out the ave of the totals sent */
	if (cpus > 0) {
		ave_vsize = (double)jobacct->tot_vsize;
		ave_vsize /= (double)cpus;
		ave_rss = (double)jobacct->tot_rss;
		ave_rss /= (double)cpus;
		ave_pages = (double)jobacct->tot_pages;
		ave_pages /= (double)cpus;
		ave_cpu = (double)jobacct->tot_cpu;
		ave_cpu /= (double)cpus;
	}

	if (jobacct->min_cpu != NO_VAL) {
		ave_cpu2 = (double)jobacct->min_cpu;
	}

	if (!step_ptr->job_ptr->db_index) {
		if (!(step_ptr->job_ptr->db_index =
		      _get_db_index(mysql_conn,
				    submit_time,
				    step_ptr->job_ptr->job_id,
				    step_ptr->job_ptr->assoc_id))) {
			/* If we get an error with this just fall
			 * through to avoid an infinite loop
			 */
			if (as_mysql_job_start(mysql_conn, step_ptr->job_ptr)
			    == SLURM_ERROR) {
				error("couldn't add job %u "
				      "at step completion",
				      step_ptr->job_ptr->job_id);
				return SLURM_SUCCESS;
			}
		}
	}

	/* The stepid could be -2 so use %d not %u */
	query = xstrdup_printf(
		"update \"%s_%s\" set time_end=%d, state=%d, "
		"kill_requid=%d, exit_code=%d, "
		"user_sec=%u, user_usec=%u, "
		"sys_sec=%u, sys_usec=%u, "
		"max_vsize=%u, max_vsize_task=%u, "
		"max_vsize_node=%u, ave_vsize=%f, "
		"max_rss=%u, max_rss_task=%u, "
		"max_rss_node=%u, ave_rss=%f, "
		"max_pages=%u, max_pages_task=%u, "
		"max_pages_node=%u, ave_pages=%f, "
		"min_cpu=%f, min_cpu_task=%u, "
		"min_cpu_node=%u, ave_cpu=%f "
		"where job_db_inx=%d and id_step=%d",
		mysql_conn->cluster_name, step_table, (int)now,
		comp_status,
		step_ptr->requid,
		exit_code,
		/* user seconds */
		jobacct->user_cpu_sec,
		/* user microseconds */
		jobacct->user_cpu_usec,
		/* system seconds */
		jobacct->sys_cpu_sec,
		/* system microsecs */
		jobacct->sys_cpu_usec,
		jobacct->max_vsize,	/* max vsize */
		jobacct->max_vsize_id.taskid,	/* max vsize task */
		jobacct->max_vsize_id.nodeid,	/* max vsize node */
		ave_vsize,	/* ave vsize */
		jobacct->max_rss,	/* max vsize */
		jobacct->max_rss_id.taskid,	/* max rss task */
		jobacct->max_rss_id.nodeid,	/* max rss node */
		ave_rss,	/* ave rss */
		jobacct->max_pages,	/* max pages */
		jobacct->max_pages_id.taskid,	/* max pages task */
		jobacct->max_pages_id.nodeid,	/* max pages node */
		ave_pages,	/* ave pages */
		ave_cpu2,	/* min cpu */
		jobacct->min_cpu_id.taskid,	/* min cpu task */
		jobacct->min_cpu_id.nodeid,	/* min cpu node */
		ave_cpu,	/* ave cpu */
		step_ptr->job_ptr->db_index, step_ptr->step_id);
	debug3("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);

	return rc;
}
示例#8
0
文件: 6-1.c 项目: shubmit/shub-ltp
int main(void)
{
#ifdef _POSIX_MEMORY_PROTECTION
	char tmpfname[256];
	void *pa;
	size_t size = 1024;
	int fd;


	pid_t child;
	int status;
	int sig_num;

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_mmap_6_1_%d", getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
	if (fd == -1) {
		printf("Error at open(): %s\n", strerror(errno));
		return PTS_UNRESOLVED;
	}
	unlink(tmpfname);

	child = fork();

	switch (child) {
	case 0:
		if (ftruncate(fd, size) == -1) {
			printf("Error at ftruncate(): %s\n",
			       strerror(errno));
			return PTS_UNRESOLVED;
		}

		pa = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
		if (pa == MAP_FAILED) {
			printf("Error at mmap: %s\n",
			       strerror(errno));
			return PTS_FAIL;
		}

		*(char *)pa = 'b';
		return 0;
	break;
	case -1:
		printf("Error at fork(): %s\n", strerror(errno));
		return PTS_UNRESOLVED;
	break;
	default:
	break;
	}

	waitpid(child, &status, WUNTRACED);
	close(fd);

	if (WIFSIGNALED(status)) {
		sig_num = WTERMSIG(status);
		printf("Child process terminated by signal %d\n", sig_num);
		if (sig_num == SIGSEGV) {
			printf("Got SIGSEGV when writing to the mapped memory, "
			       "without setting PROT_WRITE\n"
			       "Test PASSED\n");
			return PTS_PASS;
		}
	}

	if (WIFEXITED(status)) {
		if (WEXITSTATUS(status) == 0) {
			printf("Did not got SIGSEGV when writing to the mapped memory,"
			       " without setting PROT_WRITE\n"
			       "Test FAILED\n");
			return PTS_FAIL;
		}
	}

	printf("Test Unresolved\n");
	return PTS_UNRESOLVED;
#else
	printf("Test Unsupported, _POSIX_MEMORY_PROTECTION not defined\n");
	return PTS_UNSUPPORTED;
#endif
}
示例#9
0
static void summarize (FILE *fp, const char *fmt, char **command, resource_t *resp)
{
    unsigned long r;		/* Elapsed real milliseconds.  */
    unsigned long v;		/* Elapsed virtual (CPU) milliseconds.  */

    if (WIFSTOPPED (resp->waitstatus))
	fprintf (fp, "Command stopped by signal %d\n", WSTOPSIG (resp->waitstatus));
    else if (WIFSIGNALED (resp->waitstatus))
	fprintf (fp, "Command terminated by signal %d\n", WTERMSIG (resp->waitstatus));
    else if (WIFEXITED (resp->waitstatus) && WEXITSTATUS (resp->waitstatus))
	fprintf (fp, "Command exited with non-zero status %d\n", WEXITSTATUS (resp->waitstatus));

    /* Convert all times to milliseconds.  Occasionally, one of these values
       comes out as zero.  Dividing by zero causes problems, so we first
       check the time value.  If it is zero, then we take `evasive action'
       instead of calculating a value.  */

    r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000;

    v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
	resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;

    while (*fmt)
    {
	switch (*fmt)
	{
	    case '%':
		switch (*++fmt)
		{
		    case '%':		/* Literal '%'.  */
			putc ('%', fp);
			break;
		    case 'C':		/* The command that got timed.  */
			fprintargv (fp, command, " ");
			break;
		    case 'D':		/* Average unshared data size.  */
			fprintf (fp, "%lu",
				MSEC_TO_TICKS (v) == 0 ? 0 :
				ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v) +
				ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v));
			break;
		    case 'E':		/* Elapsed real (wall clock) time.  */
			if (resp->elapsed.tv_sec >= 3600)	/* One hour -> h:m:s.  */
			    fprintf (fp, "%ldh %ldm %02lds",
				    resp->elapsed.tv_sec / 3600,
				    (resp->elapsed.tv_sec % 3600) / 60,
				    resp->elapsed.tv_sec % 60);
			else
			    fprintf (fp, "%ldm %ld.%02lds",	/* -> m:s.  */
				    resp->elapsed.tv_sec / 60,
				    resp->elapsed.tv_sec % 60,
				    resp->elapsed.tv_usec / 10000);
			break;
		    case 'F':		/* Major page faults.  */
			fprintf (fp, "%ld", resp->ru.ru_majflt);
			break;
		    case 'I':		/* Inputs.  */
			fprintf (fp, "%ld", resp->ru.ru_inblock);
			break;
		    case 'K':		/* Average mem usage == data+stack+text.  */
			fprintf (fp, "%lu",
				MSEC_TO_TICKS (v) == 0 ? 0 :
				ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v) +
				ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v) +
				ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v));
			break;
		    case 'M':		/* Maximum resident set size.  */
			fprintf (fp, "%lu", ptok ((UL) resp->ru.ru_maxrss));
			break;
		    case 'O':		/* Outputs.  */
			fprintf (fp, "%ld", resp->ru.ru_oublock);
			break;
		    case 'P':		/* Percent of CPU this job got.  */
			/* % cpu is (total cpu time)/(elapsed time).  */
			if (r > 0)
			    fprintf (fp, "%lu%%", (v * 100 / r));
			else
			    fprintf (fp, "?%%");
			break;
		    case 'R':		/* Minor page faults (reclaims).  */
			fprintf (fp, "%ld", resp->ru.ru_minflt);
			break;
		    case 'S':		/* System time.  */
			fprintf (fp, "%ld.%02ld",
				resp->ru.ru_stime.tv_sec,
				resp->ru.ru_stime.TV_MSEC / 10);
			break;
		    case 'T':		/* System time.  */
			if (resp->ru.ru_stime.tv_sec >= 3600)	/* One hour -> h:m:s.  */
			    fprintf (fp, "%ldh %ldm %02lds",
				    resp->ru.ru_stime.tv_sec / 3600,
				    (resp->ru.ru_stime.tv_sec % 3600) / 60,
				    resp->ru.ru_stime.tv_sec % 60);
			else
			    fprintf (fp, "%ldm %ld.%02lds",	/* -> m:s.  */
				    resp->ru.ru_stime.tv_sec / 60,
				    resp->ru.ru_stime.tv_sec % 60,
				    resp->ru.ru_stime.tv_usec / 10000);
			break;
		    case 'U':		/* User time.  */
			fprintf (fp, "%ld.%02ld",
				resp->ru.ru_utime.tv_sec,
				resp->ru.ru_utime.TV_MSEC / 10);
			break;
		    case 'u':		/* User time.  */
			if (resp->ru.ru_utime.tv_sec >= 3600)	/* One hour -> h:m:s.  */
			    fprintf (fp, "%ldh %ldm %02lds",
				    resp->ru.ru_utime.tv_sec / 3600,
				    (resp->ru.ru_utime.tv_sec % 3600) / 60,
				    resp->ru.ru_utime.tv_sec % 60);
			else
			    fprintf (fp, "%ldm %ld.%02lds",	/* -> m:s.  */
				    resp->ru.ru_utime.tv_sec / 60,
				    resp->ru.ru_utime.tv_sec % 60,
				    resp->ru.ru_utime.tv_usec / 10000);
			break;
		    case 'W':		/* Times swapped out.  */
			fprintf (fp, "%ld", resp->ru.ru_nswap);
			break;
		    case 'X':		/* Average shared text size.  */
			fprintf (fp, "%lu",
				MSEC_TO_TICKS (v) == 0 ? 0 :
				ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v));
			break;
		    case 'Z':		/* Page size.  */
			fprintf (fp, "%d", getpagesize ());
			break;
		    case 'c':		/* Involuntary context switches.  */
			fprintf (fp, "%ld", resp->ru.ru_nivcsw);
			break;
		    case 'e':		/* Elapsed real time in seconds.  */
			fprintf (fp, "%ld.%02ld",
				resp->elapsed.tv_sec,
				resp->elapsed.tv_usec / 10000);
			break;
		    case 'k':		/* Signals delivered.  */
			fprintf (fp, "%ld", resp->ru.ru_nsignals);
			break;
		    case 'p':		/* Average stack segment.  */
			fprintf (fp, "%lu",
				MSEC_TO_TICKS (v) == 0 ? 0 :
				ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v));
			break;
		    case 'r':		/* Incoming socket messages received.  */
			fprintf (fp, "%ld", resp->ru.ru_msgrcv);
			break;
		    case 's':		/* Outgoing socket messages sent.  */
			fprintf (fp, "%ld", resp->ru.ru_msgsnd);
			break;
		    case 't':		/* Average resident set size.  */
			fprintf (fp, "%lu",
				MSEC_TO_TICKS (v) == 0 ? 0 :
				ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v));
			break;
		    case 'w':		/* Voluntary context switches.  */
			fprintf (fp, "%ld", resp->ru.ru_nvcsw);
			break;
		    case 'x':		/* Exit status.  */
			fprintf (fp, "%d", WEXITSTATUS (resp->waitstatus));
			break;
		    case '\0':
			putc ('?', fp);
			return;
		    default:
			putc ('?', fp);
			putc (*fmt, fp);
		}
		++fmt;
		break;

	    case '\\':		/* Format escape.  */
		switch (*++fmt)
		{
		    case 't':
			putc ('\t', fp);
			break;
		    case 'n':
			putc ('\n', fp);
			break;
		    case '\\':
			putc ('\\', fp);
			break;
		    default:
			putc ('?', fp);
			putc ('\\', fp);
			putc (*fmt, fp);
		}
		++fmt;
		break;

	    default:
		putc (*fmt++, fp);
	}

	if (ferror (fp))
	    bb_error_msg_and_die("write error");
    }
    putc ('\n', fp);

    if (ferror (fp))
	bb_error_msg_and_die("write error");
}
示例#10
0
int
mu_progmailer_send (struct _mu_progmailer *pm, mu_message_t msg)
{
  int status;
  mu_stream_t stream = NULL;
  char buffer[512];
  size_t len = 0;
  int rc;
  mu_header_t hdr;
  mu_body_t body;
  int found_nl = 0;
  int exit_status;
	
  if (!pm || !msg)
    return EINVAL;
  mu_message_get_header (msg, &hdr);
  status = mu_header_get_streamref (hdr, &stream);
  if (status)
    {
      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		("cannot get header stream: %s", mu_strerror (status)));
      return status;
    }
  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE, ("Sending headers..."));
  mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
  while ((status = mu_stream_readline (stream, buffer, sizeof (buffer),
				       &len)) == 0
	 && len != 0)
    {
      if (mu_c_strncasecmp (buffer, MU_HEADER_FCC, sizeof (MU_HEADER_FCC) - 1))
	{
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_PROT, ("Header: %s", buffer));
	  if (write (pm->fd, buffer, len) == -1)
	    {
	      status = errno;
	      
	      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
			("write failed: %s", strerror (status)));
	      break;
	    }
	}
      found_nl = (len == 1 && buffer[0] == '\n');
    }

  if (!found_nl)
    {
      if (write (pm->fd, "\n", 1) == -1)
	{
	  status = errno;
		
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		    ("write failed: %s", strerror (status)));
	}
    }
  mu_stream_destroy (&stream);
  
  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE, ("Sending body..."));
  mu_message_get_body (msg, &body);
  status = mu_body_get_streamref (body, &stream);
  if (status)
    {
      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		("cannot get body stream: %s\n", mu_strerror (status)));
      return status;
    }

  mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
  while ((status = mu_stream_read (stream, buffer, sizeof (buffer),
				   &len)) == 0
	 && len != 0)
    {
      if (write (pm->fd, buffer, len) == -1)
	{
	  status = errno;
	  
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		    ("write failed: %s\n", strerror (status)));
	  break;
	}
    }
  mu_body_get_streamref (body, &stream);

  close (pm->fd);

  rc = waitpid (pm->pid, &exit_status, 0);
  if (status == 0)
    {
      if (rc < 0)
	{
	  if (errno == ECHILD)
	    status = 0;
	  else
	    { 
	      status = errno;
	      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
			("waitpid(%lu) failed: %s\n",
			 (unsigned long) pm->pid, strerror (status)));
	    }
	}
      else if (WIFEXITED (exit_status))
	{
	  exit_status = WEXITSTATUS (exit_status);
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE,
		    ("%s exited with: %d\n",
		     pm->command, exit_status));
	  status = (exit_status == 0) ? 0 : MU_ERR_PROCESS_EXITED;
	}
      else if (WIFSIGNALED (exit_status))
	status = MU_ERR_PROCESS_SIGNALED;
      else
	status = MU_ERR_PROCESS_UNKNOWN_FAILURE;
    }
  pm->pid = -1;
  return status;
}
示例#11
0
extern int run_parts(char **args, const unsigned char test_mode)
{
	struct dirent **namelist = 0;
	struct stat st;
	char *filename;
	char *arg0 = args[0];
	int entries;
	int i;
	int exitstatus = 0;

#if __GNUC__
	/* Avoid longjmp clobbering */
	(void) &i;
	(void) &exitstatus;
#endif
	/* scandir() isn't POSIX, but it makes things easy. */
	entries = scandir(arg0, &namelist, valid_name, alphasort);

	if (entries == -1) {
		if (test_mode & 2) {
			return(2);
		}
		bb_perror_msg_and_die("failed to open directory %s", arg0);
	}

	for (i = 0; i < entries; i++) {

		filename = concat_path_file(arg0, namelist[i]->d_name);

		if (stat(filename, &st) < 0) {
			bb_perror_msg_and_die("failed to stat component %s", filename);
		}
		if (S_ISREG(st.st_mode) && !access(filename, X_OK)) {
			if (test_mode & 1) {
				puts(filename);
			} else {
				/* exec_errno is common vfork variable */
				volatile int exec_errno = 0;
				int result;
				int pid;

				if ((pid = vfork()) < 0) {
					bb_perror_msg_and_die("failed to fork");
				} else if (!pid) {
					args[0] = filename;
					execv(filename, args);
					exec_errno = errno;
					_exit(1);
				}

				waitpid(pid, &result, 0);
				if(exec_errno) {
					errno = exec_errno;
					bb_perror_msg_and_die("failed to exec %s", filename);
				}
				if (WIFEXITED(result) && WEXITSTATUS(result)) {
					bb_perror_msg("%s exited with return code %d", filename, WEXITSTATUS(result));
					exitstatus = 1;
				} else if (WIFSIGNALED(result)) {
					bb_perror_msg("%s exited because of uncaught signal %d", filename, WTERMSIG(result));
					exitstatus = 1;
				}
			}
		} 
		else if (!S_ISDIR(st.st_mode)) {
			bb_error_msg("component %s is not an executable plain file", filename);
			exitstatus = 1;
		}

		free(namelist[i]);
		free(filename);
	}
	free(namelist);
	
	return(exitstatus);
}
示例#12
0
RTR3DECL(int)   RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
{
    /*
     * Validate input.
     */
    if (Process <= 0)
    {
        AssertMsgFailed(("Invalid Process=%d\n", Process));
        return VERR_INVALID_PARAMETER;
    }
    if (fFlags & ~(RTPROCWAIT_FLAGS_NOBLOCK | RTPROCWAIT_FLAGS_BLOCK))
    {
        AssertMsgFailed(("Invalid flags %#x\n", fFlags));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Perform the wait.
     */
    int iStatus = 0;
    int rc = waitpid(Process, &iStatus, fFlags & RTPROCWAIT_FLAGS_NOBLOCK ? WNOHANG : 0);
    if (rc > 0)
    {
        /*
         * Fill in the status structure.
         */
        if (pProcStatus)
        {
            if (WIFEXITED(iStatus))
            {
                pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
                pProcStatus->iStatus = WEXITSTATUS(iStatus);
            }
            else if (WIFSIGNALED(iStatus))
            {
                pProcStatus->enmReason = RTPROCEXITREASON_SIGNAL;
                pProcStatus->iStatus = WTERMSIG(iStatus);
            }
            else
            {
                Assert(!WIFSTOPPED(iStatus));
                pProcStatus->enmReason = RTPROCEXITREASON_ABEND;
                pProcStatus->iStatus = iStatus;
            }
        }
        return VINF_SUCCESS;
    }

    /*
     * Child running?
     */
    if (!rc)
    {
        Assert(fFlags & RTPROCWAIT_FLAGS_NOBLOCK);
        return VERR_PROCESS_RUNNING;
    }

    /*
     * Figure out which error to return.
     */
    int iErr = errno;
    if (iErr == ECHILD)
        return VERR_PROCESS_NOT_FOUND;
    return RTErrConvertFromErrno(iErr);
}
示例#13
0
static int do_test(void)
{
    int *addr;                  /* Pointer to shared memory region */
    int status;
    /* Parent creates mapped region prior to calling fork() */

#ifdef USE_MAP_ANON             /* Use MAP_ANONYMOUS */
    addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if (addr == MAP_FAILED){
        fprintf(stderr,"mmap failed - errno = %d\n",errno);
        exit(-1);
    }

#else                           /* Map /dev/zero */
    int fd;

    fd = open("/dev/zero", O_RDWR);
    if (fd == -1)
        errExit("open");

    addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED)
        errExit("mmap");

    if (close(fd) == -1)        /* No longer needed */
        errExit("close");
#endif

    /*
     * Part 1. Test successful parent-chlid-grandchild access.
     */

    *addr = 1;                  /* Initialize integer in mapped region */

    switch (fork()) {           /* Parent and child share mapping */
    case -1:
        fprintf(stderr,"fork failed - errno = %d\n",errno);
	exit(-1);
    case 0:                     /* Child: increment shared integer and exit */
        printf("Child started, ");
        printf("value = %d\n", *addr);
        (*addr)++;
        if (*addr != 2) {
            fprintf(stderr,"value is %d, must be 2\n",*addr);
            exit(-1);
        }
        switch (fork()) {       /* Parent and child share mapping */
        case -1:
            fprintf(stderr,"fork failed - errno = %d\n",errno);
            exit(-1);
        case 0:                 /* Child: increment shared integer and exit */
            printf("Grand child started, ");
            printf("value = %d\n", *addr);
            (*addr)++;
            if (*addr != 3) {
                fprintf(stderr,"value is %d, must be 3\n",*addr);
                exit(-1);
            }
            if (munmap(addr, sizeof(int)) == -1){
                fprintf(stderr,"munmap failed - errno = %d\n",errno);
                exit(-1);
            }
            exit(EXIT_SUCCESS);
        default:                /* Parent: wait for child to terminate */
            if (wait(&status) == -1){
                fprintf(stderr,"wait failed - errno = %d\n",errno);
                exit(-1);
            }
            if (!WIFEXITED(status) || WEXITSTATUS(status)) {
                fprintf(stderr,"child crashed or returned non-zero (status %x)\n", status);
                exit(-1);
            }
            printf("In child, value = %d\n", *addr);
            if (*addr != 3) {
                fprintf(stderr,"value is %d, must be 3\n",*addr);
                exit(-1);
            }
            if (munmap(addr, sizeof(int)) == -1){
                fprintf(stderr,"munmap failed - errno = %d\n",errno);
                exit(-1);
            }
            exit(EXIT_SUCCESS);
        }

    default:                    /* Parent: wait for child to terminate */
        if (wait(&status) == -1){
	    fprintf(stderr,"wait failed - errno = %d\n",errno);
	    exit(-1);
	}
        if (!WIFEXITED(status) || WEXITSTATUS(status)) {
            fprintf(stderr,"child crashed or returned non-zero (status %x)\n", status);
            exit(-1);
	}
        printf("In parent, value = %d\n", *addr);
        if (*addr != 3) {
            fprintf(stderr,"value is %d, must be 3\n",*addr);
            exit(-1);
        }
    }

    /*
     * Part 2. Test unsuccessful parent-chlid access.
     */

    switch (fork()) {           /* Parent and child share mapping */
    case -1:
        fprintf(stderr,"fork failed - errno = %d\n",errno);
	exit(-1);
    case 0:                     /* Child: increment shared integer and exit */
        printf("Child started, ");
        printf("value = %d\n", *addr);
        (*addr)++;
        if (*addr != 4) {
            fprintf(stderr,"value is %d, must be 4\n",*addr);
            exit(-1);
        }
        if (munmap(addr, sizeof(int)) == -1){
                fprintf(stderr,"munmap failed - errno = %d\n",errno);
                exit(-1);
        }
        /* This should crash the child with SIGSEGV */
        (*addr)++;
        exit(EXIT_SUCCESS);
    default:                    /* Parent: wait for child to terminate */
        if (wait(&status) == -1){
            fprintf(stderr,"wait failed - errno = %d\n",errno);
            exit(-1);
        }
        if (WIFEXITED(status) || !WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) {
            fprintf(stderr,"child ended sucessfully or crashed not with SIGSEGV (status %x)\n", status);
            exit(-1);
        }
        printf("In parent, value = %d\n", *addr);
        if (*addr != 4) {
            fprintf(stderr,"value is %d, must be 4\n",*addr);
            exit(-1);
        }
        if (munmap(addr, sizeof(int)) == -1){
            fprintf(stderr,"munmap failed - errno = %d\n",errno);
            exit(-1);
        }
        exit(EXIT_SUCCESS);
    }
}
示例#14
0
文件: pidns17.c 项目: AbhiramiP/ltp
/*
 * child_fn() - Inside container
 */
int child_fn(void *arg)
{
	int children[10], exit_val, i, status;
	pid_t pid, ppid;

	/* Set process id and parent pid */
	pid = getpid();
	ppid = getppid();
	if (pid != CHILD_PID || ppid != PARENT_PID) {
		printf("cinit: pidns was not created\n");
		exit(1);
	}

	exit_val = 0;

	/* Spawn many children */
	for (i = 0; i < (sizeof(children) / sizeof(children[0])); i++) {
		switch ((children[i] = fork())) {
		case -1:
			perror("fork failed");
			exit_val = 1;
			break;
		case 0:
			pause();
			/* XXX (garrcoop): why exit with an exit code of 2? */
			exit(2);
			break;
		default:
			/* fork succeeded. */
			break;
		}
	}
	/* wait for last child to get scheduled */
	sleep(1);

	if (kill(-1, SIGUSR1) == -1) {
		perror("cinit: kill(-1, SIGUSR1) failed");
		exit_val = 1;
	}

	for (i = 0; i < (sizeof(children) / sizeof(children[0])); i++) {
		if (waitpid(children[i], &status, 0) == -1) {
			perror("cinit: waitpid failed");
			kill(children[i], SIGTERM);
			waitpid(children[i], &status, 0);
			exit_val = 1;
		}
		if (!(WIFSIGNALED(status) || WTERMSIG(status) == SIGUSR1)) {
			/*
			 * XXX (garrcoop): this status reporting is overly
			 * noisy. Someone obviously needs to read the
			 * constraints documented in wait(2) a bit more
			 * closely -- in particular the relationship between
			 * WIFEXITED and WEXITSTATUS, and WIFSIGNALED and
			 * WTERMSIG.
			 */
			printf("cinit: found a child alive still "
			       "%d exit: %d, %d, signal %d, %d", i,
			       WIFEXITED(status), WEXITSTATUS(status),
			       WIFSIGNALED(status), WTERMSIG(status));
			exit_val = 1;
		}
	}
	if (exit_val == 0)
		printf("cinit: all children have terminated.\n");

	exit(exit_val);
}
示例#15
0
int
main(int argc, char **argv)
{
	int ch;
	unsigned long i;
	int foreground, preserve;
	int error, pstat, status;
	int killsig = SIGTERM;
	pid_t pid, cpid;
	double first_kill;
	double second_kill;
	bool timedout = false;
	bool do_second_kill = false;
	bool child_done = false;
	struct sigaction signals;
	struct procctl_reaper_status info;
	struct procctl_reaper_kill killemall;
	int signums[] = {
		-1,
		SIGTERM,
		SIGINT,
		SIGHUP,
		SIGCHLD,
		SIGALRM,
		SIGQUIT,
	};

	foreground = preserve = 0;
	second_kill = 0;

	const struct option longopts[] = {
		{ "preserve-status", no_argument,       &preserve,    1 },
		{ "foreground",      no_argument,       &foreground,  1 },
		{ "kill-after",      required_argument, NULL,        'k'},
		{ "signal",          required_argument, NULL,        's'},
		{ "help",            no_argument,       NULL,        'h'},
		{ NULL,              0,                 NULL,         0 }
	};

	while ((ch = getopt_long(argc, argv, "+k:s:h", longopts, NULL)) != -1) {
		switch (ch) {
			case 'k':
				do_second_kill = true;
				second_kill = parse_duration(optarg);
				break;
			case 's':
				killsig = parse_signal(optarg);
				break;
			case 0:
				break;
			case 'h':
			default:
				usage();
				break;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 2)
		usage();

	first_kill = parse_duration(argv[0]);
	argc--;
	argv++;

	if (!foreground) {
		/* Aquire a reaper */
		if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1)
			err(EX_OSERR, "Fail to acquire the reaper");
	}

	memset(&signals, 0, sizeof(signals));
	sigemptyset(&signals.sa_mask);

	if (killsig != SIGKILL && killsig != SIGSTOP)
		signums[0] = killsig;

	for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i ++)
		sigaddset(&signals.sa_mask, signums[i]);

	signals.sa_handler = sig_handler;
	signals.sa_flags = SA_RESTART;

	for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i ++)
		if (signums[i] != -1 && signums[i] != 0 &&
		    sigaction(signums[i], &signals, NULL) == -1)
			err(EX_OSERR, "sigaction()");

	signal(SIGTTIN, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);

	pid = fork();
	if (pid == -1)
		err(EX_OSERR, "fork()");
	else if (pid == 0) {
		/* child process */
		signal(SIGTTIN, SIG_DFL);
		signal(SIGTTOU, SIG_DFL);

		error = execvp(argv[0], argv);
		if (error == -1) {
			if (errno == ENOENT)
				err(127, "exec(%s)", argv[0]);
			else
				err(126, "exec(%s)", argv[0]);
		}
	}

	if (sigprocmask(SIG_BLOCK, &signals.sa_mask, NULL) == -1)
		err(EX_OSERR, "sigprocmask()");

	/* parent continues here */
	set_interval(first_kill);

	for (;;) {
		sigemptyset(&signals.sa_mask);
		sigsuspend(&signals.sa_mask);

		if (sig_chld) {
			sig_chld = 0;

			while ((cpid = waitpid(-1, &status, WNOHANG)) != 0) {
				if (cpid < 0) {
					if (errno == EINTR)
						continue;
					else
						break;
				} else if (cpid == pid) {
					pstat = status;
					child_done = true;
				}
			}
			if (child_done) {
				if (foreground) {
					break;
				} else {
					procctl(P_PID, getpid(),
					    PROC_REAP_STATUS, &info);
					if (info.rs_children == 0)
						break;
				}
			}
		} else if (sig_alrm) {
			sig_alrm = 0;

			timedout = true;
			if (!foreground) {
				killemall.rk_sig = killsig;
				killemall.rk_flags = 0;
				procctl(P_PID, getpid(), PROC_REAP_KILL,
				    &killemall);
			} else
				kill(pid, killsig);

			if (do_second_kill) {
				set_interval(second_kill);
				second_kill = 0;
				sig_ign = killsig;
				killsig = SIGKILL;
			} else
				break;

		} else if (sig_term) {
			if (!foreground) {
				killemall.rk_sig = sig_term;
				killemall.rk_flags = 0;
				procctl(P_PID, getpid(), PROC_REAP_KILL,
				    &killemall);
			} else
				kill(pid, sig_term);

			if (do_second_kill) {
				set_interval(second_kill);
				second_kill = 0;
				sig_ign = killsig;
				killsig = SIGKILL;
			} else
				break;
		}
	}

	while (!child_done && wait(&pstat) == -1) {
		if (errno != EINTR)
			err(EX_OSERR, "waitpid()");
	}

	if (!foreground)
		procctl(P_PID, getpid(), PROC_REAP_RELEASE, NULL);

	if (WEXITSTATUS(pstat))
		pstat = WEXITSTATUS(pstat);
	else if(WIFSIGNALED(pstat))
		pstat = 128 + WTERMSIG(pstat);

	if (timedout && !preserve)
		pstat = EXIT_TIMEOUT;

	return (pstat);
}
示例#16
0
/**
 * Signal handler for the server.
 */
void handle_sigs(void)
{
	pid_t  chld;
	int    chld_status;
	int    i;
	int    do_exit;

	switch(sig_flag){
		case 0: break; /* do nothing*/
		case SIGPIPE:
				/* SIGPIPE might be rarely received on use of
				   exec module; simply ignore it
				 */
				LM_WARN("SIGPIPE received and ignored\n");
				break;
		case SIGINT:
		case SIGTERM:
			/* we end the program in all these cases */
			if (sig_flag==SIGINT)
				LM_DBG("INT received, program terminates\n");
			else
				LM_DBG("SIGTERM received, program terminates\n");
				
			/* first of all, kill the children also */
			kill_all_children(SIGTERM);
			if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) {
				LM_ERR("could not install SIGALARM handler\n");
				/* continue, the process will die anyway if no
				 * alarm is installed which is exactly what we want */
			}
			alarm(OPENSER_SHUTDOWN_TIME); /* 1 minute close timeout */

			while(wait(0) > 0); /* Wait for all the children to terminate */
			signal(SIGALRM, sig_alarm_abort);

			cleanup(1); /* cleanup & show status*/
			alarm(0);
			signal(SIGALRM, SIG_IGN);
			dprint("Thank you for flying " NAME "\n");
			exit(0);
			break;
			
		case SIGUSR1:
#ifdef PKG_MALLOC
			LOG(memlog, "Memory status (pkg):\n");
			pkg_status();
#endif
#ifdef SHM_MEM
			LOG(memlog, "Memory status (shm):\n");
			shm_status();
#endif
			break;
			
		case SIGCHLD:
			do_exit = 0;
			while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
				/* is it a process we know about? */
				for( i=0 ; i<counted_processes ; i++ )
					if (pt[i].pid==chld) break;
				if (i==counted_processes) {
					LM_DBG("unkown child process %d ended. Ignoring\n",chld);
					continue;
				}
				do_exit = 1;
				/* process the signal */
				if (WIFEXITED(chld_status)) 
					LM_INFO("child process %d exited normally,"
							" status=%d\n", chld, 
							WEXITSTATUS(chld_status));
				else if (WIFSIGNALED(chld_status)) {
					LM_INFO("child process %d exited by a signal"
							" %d\n", chld, WTERMSIG(chld_status));
#ifdef WCOREDUMP
					LM_INFO("core was %sgenerated\n",
							 WCOREDUMP(chld_status) ?  "" : "not " );
#endif
				}else if (WIFSTOPPED(chld_status)) 
					LM_INFO("child process %d stopped by a"
								" signal %d\n", chld,
								 WSTOPSIG(chld_status));
			}
			if (!do_exit)
				break;
			LM_INFO("terminating due to SIGCHLD\n");
			/* exit */
			kill_all_children(SIGTERM);
			if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) {
				LM_ERR("could not install SIGALARM handler\n");
				/* continue, the process will die anyway if no
				 * alarm is installed which is exactly what we want */
			}
			alarm(OPENSER_SHUTDOWN_TIME); /* 1 minute close timeout */
			while(wait(0) > 0); /* wait for all the children to terminate*/
			signal(SIGALRM, sig_alarm_abort);
			cleanup(1); /* cleanup & show status*/
			alarm(0);
			signal(SIGALRM, SIG_IGN);
			LM_DBG("terminating due to SIGCHLD\n");
			exit(0);
			break;
		
		case SIGHUP: /* ignoring it*/
			LM_DBG("SIGHUP received, ignoring it\n");
			break;
		default:
			LM_CRIT("unhandled signal %d\n", sig_flag);
	}
	sig_flag=0;
}
示例#17
0
static int
fd_data (socket_t fd,
         int revents,
         gpointer user_data)
{
  ssh_channel chan = (ssh_channel)user_data;
  guint8 buf[BUFSIZE];
  gint sz = 0;
  gint bytes = 0;
  gint status;
  gint written;
  pid_t pid = 0;
  gboolean end = FALSE;
  gint ret;

  if (revents & POLLIN)
    {
      int ws;
      do
        {
          ws = ssh_channel_window_size (chan);
          ws = ws < BUFSIZE ? ws : BUFSIZE;
          if (ws == 0)
            break;
          bytes = read (fd, buf, ws);
          if (bytes < 0)
            {
              if (errno == EAGAIN)
                break;
              if (errno != ECONNRESET && errno != EBADF)
                g_critical ("couldn't read from process: %m");
              end = TRUE;
              break;
            }
          else if (bytes == 0)
            {
              end = TRUE;
            }
          else
            {
              sz += bytes;
              written = ssh_channel_write (chan, buf, bytes);
              if (written != bytes)
                g_assert_not_reached ();
            }
        }
      while (bytes == ws);
    }
  if ((revents & POLLOUT))
    {
      if (state.buffer->len > 0)
        {
          written = write (fd, state.buffer->data, state.buffer->len);
          if (written < 0 && errno != EAGAIN)
            g_critical ("couldn't write: %s", g_strerror (errno));
          if (written > 0)
            g_byte_array_remove_range (state.buffer, 0, written);
        }
      if (state.buffer_eof && state.buffer->len == 0)
        {
          if (shutdown (fd, SHUT_WR) < 0)
            {
              if (errno != EAGAIN && errno != EBADF)
                g_critical ("couldn't shutdown: %s", g_strerror (errno));
            }
          else
            {
              state.buffer_eof = FALSE;
            }
        }
    }
  if (end || (revents & (POLLHUP | POLLERR | POLLNVAL)))
    {
      ssh_channel_send_eof (chan);
      pid = waitpid (state.childpid, &status, 0);
      if (pid < 0)
        {
          g_critical ("couldn't wait on child process: %m");
        }
      else
        {
          if (WIFSIGNALED (status))
            ssh_channel_request_send_exit_signal (chan, strsignal (WTERMSIG (status)), 0, "", "");
          else
            ssh_channel_request_send_exit_status (chan, WEXITSTATUS (status));
        }
      ret = ssh_blocking_flush (state.session, -1);
      if (ret != SSH_OK && ret != SSH_CLOSED)
        g_message ("ssh_blocking_flush() failed: %d", ret);
      ssh_channel_close (chan);
      ssh_channel_free (chan);
      ret = ssh_blocking_flush (state.session, -1);
      if (ret != SSH_OK && ret != SSH_CLOSED)
        g_message ("ssh_blocking_flush() failed: %d", ret);
      state.channel = NULL;
      ssh_event_remove_fd (state.event, fd);
      sz = -1;
    }

  return sz;
}
示例#18
0
static void
mgt_reap_child(void)
{
	int i;
	int status = 0xffff;
	struct vsb *vsb;
	pid_t r = 0;

	assert(child_pid != -1);

	/*
	 * Close the CLI connections
	 * This signals orderly shut down to child
	 */
	mgt_cli_stop_child();
	if (child_cli_out >= 0)
		closex(&child_cli_out);
	if (child_cli_in >= 0)
		closex(&child_cli_in);

	/* Stop the poker */
	if (ev_poker != NULL) {
		vev_del(mgt_evb, ev_poker);
		free(ev_poker);
	}
	ev_poker = NULL;

	/* Stop the listener */
	if (ev_listen != NULL) {
		vev_del(mgt_evb, ev_listen);
		free(ev_listen);
		ev_listen = NULL;
	}

	/* Compose obituary */
	vsb = VSB_new_auto();
	XXXAN(vsb);

	/* Wait for child to die */
	for (i = 0; i < mgt_param.cli_timeout; i++) {
		r = waitpid(child_pid, &status, WNOHANG);
		if (r == child_pid)
			break;
		(void)sleep(1);
	}
	if (r == 0) {
		VSB_printf(vsb, "Child (%jd) not dying, killing", (intmax_t)r);

		/* Kick it Jim... */
		if (MGT_FEATURE(FEATURE_NO_COREDUMP))
			(void)kill(child_pid, SIGKILL);
		else
			(void)kill(child_pid, SIGQUIT);
		r = waitpid(child_pid, &status, 0);
	}
	if (r != child_pid)
		fprintf(stderr, "WAIT 0x%jx\n", (uintmax_t)r);
	assert(r == child_pid);

	MAC_reopen_sockets(NULL);

	VSB_printf(vsb, "Child (%jd) %s", (intmax_t)r,
	    status ? "died" : "ended");
	if (WIFEXITED(status) && WEXITSTATUS(status)) {
		VSB_printf(vsb, " status=%d", WEXITSTATUS(status));
		exit_status |= 0x20;
		if (WEXITSTATUS(status) == 1)
			VSC_C_mgt->child_exit = ++static_VSC_C_mgt.child_exit;
		else
			VSC_C_mgt->child_stop = ++static_VSC_C_mgt.child_stop;
	}
	if (WIFSIGNALED(status)) {
		VSB_printf(vsb, " signal=%d", WTERMSIG(status));
		exit_status |= 0x40;
		VSC_C_mgt->child_died = ++static_VSC_C_mgt.child_died;
	}
#ifdef WCOREDUMP
	if (WCOREDUMP(status)) {
		VSB_printf(vsb, " (core dumped)");
		exit_status |= 0x80;
		VSC_C_mgt->child_dump = ++static_VSC_C_mgt.child_dump;
	}
#endif
	AZ(VSB_finish(vsb));
	MGT_complain(status ? C_ERR : C_INFO, "%s", VSB_data(vsb));
	VSB_destroy(&vsb);

	/* Dispose of shared memory but evacuate panic messages first */
	if (heritage.panic_str[0] != '\0') {
		mgt_panic_record(r);
		mgt_SHM_Destroy(1);
		VSC_C_mgt->child_panic = ++static_VSC_C_mgt.child_panic;
	} else {
		mgt_SHM_Destroy(MGT_DO_DEBUG(DBG_VSM_KEEP));
	}
	mgt_SHM_Create();
	mgt_SHM_Commit();

	if (child_state == CH_RUNNING)
		child_state = CH_DIED;

	/* Pick up any stuff lingering on stdout/stderr */
	(void)child_listener(NULL, EV_RD);
	closex(&child_output);
	VLU_Destroy(child_std_vlu);

	child_pid = -1;

	MGT_complain(C_DEBUG, "Child cleanup complete");

	if (child_state == CH_DIED && mgt_param.auto_restart)
		mgt_launch_child(NULL);
	else if (child_state == CH_DIED)
		child_state = CH_STOPPED;
	else if (child_state == CH_STOPPING)
		child_state = CH_STOPPED;
}
示例#19
0
int	check_signal(int pid, int status, t_mod_pack *packet)
{
  if (WIFSIGNALED(status) && WTERMSIG(status) == SIGHUP)
    return (my_puterr(ERR_SIGHUP));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
    return (my_puterr(ERR_SIGINT));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGQUIT)
    return (my_puterr(ERR_SIGQUIT));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGILL)
    return (my_puterr(ERR_SIGILL));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGFPE)
    return (my_puterr(ERR_SIGFPE));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)
    return (my_puterr(ERR_SIGKILL));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
    return (my_puterr(ERR_SIGSEGV));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGPIPE)
    return (my_puterr(ERR_SIGPIPE));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM)
    return (my_puterr(ERR_SIGTERM));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSTOP)
    return (my_puterr(ERR_SIGSTOP));
  else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTSTP)
    return (my_puterr(ERR_SIGTSTP));
  return (check_error(pid, status, packet));
}
示例#20
0
int
ksandbox_systrace_init_parent(void *arg, enum sandtype type, pid_t child)
{
    struct systrace_sandbox *box = arg;
    int		dev, i, j, found, st, rc;
    pid_t		pid;
    struct systrace_policy policy;
    const struct systrace_preauth *preauth;

    assert(NULL != arg);

    preauth = SAND_WORKER != type ?
              preauth_control : preauth_worker;

    rc = 0;

    /*
     * Wait for the child to send itself a SIGSTOP.
     * When we receive it, the child is waiting to be sandboxed.
     */
    do
        pid = waitpid(child, &st, WUNTRACED);
    while (pid == -1 && errno == EINTR);

    if (-1 == pid) {
        XWARN("waitpid");
        return(0);
    }

    /* Catch if it exits. */
    signal(SIGCHLD, box->osigchld);

    if ( ! WIFSTOPPED(st)) {
        if (WIFSIGNALED(st)) {
            XWARNX("child signal %d", WTERMSIG(st));
            return(0);
        } else if (WIFEXITED(st)) {
            XWARNX("child exit %d", WEXITSTATUS(st));
            return(0);
        }
        XWARNX("child not stopped");
        return(0);
    }

    box->child_pid = child;

    /* Set up systracing of child */
    if ((dev = open("/dev/systrace", O_RDONLY)) == -1) {
        if (ENXIO == errno) {
            XWARN("open: /dev/systrace (mounted nodev?)");
            goto out;
        }
        XWARN("open: /dev/systrace");
        goto out;
    }

    if (ioctl(dev, STRIOCCLONE, &box->systrace_fd) == -1) {
        XWARN("ioctl: STRIOCCLONE");
        close(dev);
        goto out;
    }

    close(dev);

    if (ioctl(box->systrace_fd, STRIOCATTACH, &child) == -1) {
        XWARN("ioctl: STRIOCATTACH");
        goto out;
    }

    /* Allocate and assign policy */
    memset(&policy, 0, sizeof(policy));
    policy.strp_op = SYSTR_POLICY_NEW;
    policy.strp_maxents = SYS_MAXSYSCALL;
    if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1) {
        XWARN("ioctl: STRIOCPOLICY (new)");
        goto out;
    }

    policy.strp_op = SYSTR_POLICY_ASSIGN;
    policy.strp_pid = box->child_pid;
    if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1) {
        XWARN("ioctl: STRIOCPOLICY (assign)");
        goto out;
    }

    /* Set per-syscall policy */
    for (i = 0; i < SYS_MAXSYSCALL; i++) {
        found = 0;
        for (j = 0; preauth[j].syscall != -1; j++) {
            if (preauth[j].syscall == i) {
                found = 1;
                break;
            }
        }
        policy.strp_op = SYSTR_POLICY_MODIFY;
        policy.strp_code = i;
        policy.strp_policy = found ?
                             preauth[j].action : SYSTR_POLICY_KILL;
        if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1) {
            XWARN("ioctl: STRIOCPOLICY (modify)");
            goto out;
        }
    }

    rc = 1;
out:
    /* Signal the child to start running */
    if (kill(box->child_pid, SIGCONT) == 0)
        return(rc);

    XWARN("kill: SIGCONT");
    return(0);
}
示例#21
0
/*
 * Exit: deallocate address space and other resources, change proc state to
 * zombie, and unlink proc from allproc and parent's lists.  Save exit status
 * and rusage for wait().  Check for child processes and orphan them.
 */
void
exit1(struct thread *td, int rv)
{
	struct proc *p, *nq, *q;
	struct vnode *vtmp;
	struct vnode *ttyvp = NULL;
	struct plimit *plim;
	int locked;

	mtx_assert(&Giant, MA_NOTOWNED);

	p = td->td_proc;
	/*
	 * XXX in case we're rebooting we just let init die in order to
	 * work around an unsolved stack overflow seen very late during
	 * shutdown on sparc64 when the gmirror worker process exists.
	 */
	if (p == initproc && rebooting == 0) {
		printf("init died (signal %d, exit %d)\n",
		    WTERMSIG(rv), WEXITSTATUS(rv));
		panic("Going nowhere without my init!");
	}

	/*
	 * MUST abort all other threads before proceeding past here.
	 */
	PROC_LOCK(p);
	while (p->p_flag & P_HADTHREADS) {
		/*
		 * First check if some other thread got here before us..
		 * if so, act apropriatly, (exit or suspend);
		 */
		thread_suspend_check(0);

		/*
		 * Kill off the other threads. This requires
		 * some co-operation from other parts of the kernel
		 * so it may not be instantaneous.  With this state set
		 * any thread entering the kernel from userspace will
		 * thread_exit() in trap().  Any thread attempting to
		 * sleep will return immediately with EINTR or EWOULDBLOCK
		 * which will hopefully force them to back out to userland
		 * freeing resources as they go.  Any thread attempting
		 * to return to userland will thread_exit() from userret().
		 * thread_exit() will unsuspend us when the last of the
		 * other threads exits.
		 * If there is already a thread singler after resumption,
		 * calling thread_single will fail; in that case, we just
		 * re-check all suspension request, the thread should
		 * either be suspended there or exit.
		 */
		if (! thread_single(SINGLE_EXIT))
			break;

		/*
		 * All other activity in this process is now stopped.
		 * Threading support has been turned off.
		 */
	}
	KASSERT(p->p_numthreads == 1,
	    ("exit1: proc %p exiting with %d threads", p, p->p_numthreads));
	racct_sub(p, RACCT_NTHR, 1);
	/*
	 * Wakeup anyone in procfs' PIOCWAIT.  They should have a hold
	 * on our vmspace, so we should block below until they have
	 * released their reference to us.  Note that if they have
	 * requested S_EXIT stops we will block here until they ack
	 * via PIOCCONT.
	 */
	_STOPEVENT(p, S_EXIT, rv);

	/*
	 * Ignore any pending request to stop due to a stop signal.
	 * Once P_WEXIT is set, future requests will be ignored as
	 * well.
	 */
	p->p_flag &= ~P_STOPPED_SIG;
	KASSERT(!P_SHOULDSTOP(p), ("exiting process is stopped"));

	/*
	 * Note that we are exiting and do another wakeup of anyone in
	 * PIOCWAIT in case they aren't listening for S_EXIT stops or
	 * decided to wait again after we told them we are exiting.
	 */
	p->p_flag |= P_WEXIT;
	wakeup(&p->p_stype);

	/*
	 * Wait for any processes that have a hold on our vmspace to
	 * release their reference.
	 */
	while (p->p_lock > 0)
		msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0);

	p->p_xstat = rv;	/* Let event handler change exit status */
	PROC_UNLOCK(p);
	/* Drain the limit callout while we don't have the proc locked */
	callout_drain(&p->p_limco);

#ifdef AUDIT
	/*
	 * The Sun BSM exit token contains two components: an exit status as
	 * passed to exit(), and a return value to indicate what sort of exit
	 * it was.  The exit status is WEXITSTATUS(rv), but it's not clear
	 * what the return value is.
	 */
	AUDIT_ARG_EXIT(WEXITSTATUS(rv), 0);
	AUDIT_SYSCALL_EXIT(0, td);
#endif

	/* Are we a task leader? */
	if (p == p->p_leader) {
		mtx_lock(&ppeers_lock);
		q = p->p_peers;
		while (q != NULL) {
			PROC_LOCK(q);
			kern_psignal(q, SIGKILL);
			PROC_UNLOCK(q);
			q = q->p_peers;
		}
		while (p->p_peers != NULL)
			msleep(p, &ppeers_lock, PWAIT, "exit1", 0);
		mtx_unlock(&ppeers_lock);
	}

	/*
	 * Check if any loadable modules need anything done at process exit.
	 * E.g. SYSV IPC stuff
	 * XXX what if one of these generates an error?
	 */
	EVENTHANDLER_INVOKE(process_exit, p);

	/*
	 * If parent is waiting for us to exit or exec,
	 * P_PPWAIT is set; we will wakeup the parent below.
	 */
	PROC_LOCK(p);
	rv = p->p_xstat;	/* Event handler could change exit status */
	stopprofclock(p);
	p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE);

	/*
	 * Stop the real interval timer.  If the handler is currently
	 * executing, prevent it from rearming itself and let it finish.
	 */
	if (timevalisset(&p->p_realtimer.it_value) &&
	    callout_stop(&p->p_itcallout) == 0) {
		timevalclear(&p->p_realtimer.it_interval);
		msleep(&p->p_itcallout, &p->p_mtx, PWAIT, "ritwait", 0);
		KASSERT(!timevalisset(&p->p_realtimer.it_value),
		    ("realtime timer is still armed"));
	}
	PROC_UNLOCK(p);

	/*
	 * Reset any sigio structures pointing to us as a result of
	 * F_SETOWN with our pid.
	 */
	funsetownlst(&p->p_sigiolst);

	/*
	 * If this process has an nlminfo data area (for lockd), release it
	 */
	if (nlminfo_release_p != NULL && p->p_nlminfo != NULL)
		(*nlminfo_release_p)(p);

	/*
	 * Close open files and release open-file table.
	 * This may block!
	 */
	fdfree(td);

	/*
	 * If this thread tickled GEOM, we need to wait for the giggling to
	 * stop before we return to userland
	 */
	if (td->td_pflags & TDP_GEOM)
		g_waitidle();

	/*
	 * Remove ourself from our leader's peer list and wake our leader.
	 */
	mtx_lock(&ppeers_lock);
	if (p->p_leader->p_peers) {
		q = p->p_leader;
		while (q->p_peers != p)
			q = q->p_peers;
		q->p_peers = p->p_peers;
		wakeup(p->p_leader);
	}
	mtx_unlock(&ppeers_lock);

	vmspace_exit(td);

	sx_xlock(&proctree_lock);
	if (SESS_LEADER(p)) {
		struct session *sp = p->p_session;
		struct tty *tp;

		/*
		 * s_ttyp is not zero'd; we use this to indicate that
		 * the session once had a controlling terminal. (for
		 * logging and informational purposes)
		 */
		SESS_LOCK(sp);
		ttyvp = sp->s_ttyvp;
		tp = sp->s_ttyp;
		sp->s_ttyvp = NULL;
		sp->s_ttydp = NULL;
		sp->s_leader = NULL;
		SESS_UNLOCK(sp);

		/*
		 * Signal foreground pgrp and revoke access to
		 * controlling terminal if it has not been revoked
		 * already.
		 *
		 * Because the TTY may have been revoked in the mean
		 * time and could already have a new session associated
		 * with it, make sure we don't send a SIGHUP to a
		 * foreground process group that does not belong to this
		 * session.
		 */

		if (tp != NULL) {
			tty_lock(tp);
			if (tp->t_session == sp)
				tty_signal_pgrp(tp, SIGHUP);
			tty_unlock(tp);
		}

		if (ttyvp != NULL) {
			sx_xunlock(&proctree_lock);
			if (vn_lock(ttyvp, LK_EXCLUSIVE) == 0) {
				VOP_REVOKE(ttyvp, REVOKEALL);
				VOP_UNLOCK(ttyvp, 0);
			}
			sx_xlock(&proctree_lock);
		}
	}
	fixjobc(p, p->p_pgrp, 0);
	sx_xunlock(&proctree_lock);
	(void)acct_process(td);

	/* Release the TTY now we've unlocked everything. */
	if (ttyvp != NULL)
		vrele(ttyvp);
#ifdef KTRACE
	ktrprocexit(td);
#endif
	/*
	 * Release reference to text vnode
	 */
	if ((vtmp = p->p_textvp) != NULL) {
		p->p_textvp = NULL;
		locked = VFS_LOCK_GIANT(vtmp->v_mount);
		vrele(vtmp);
		VFS_UNLOCK_GIANT(locked);
	}

	/*
	 * Release our limits structure.
	 */
	PROC_LOCK(p);
	plim = p->p_limit;
	p->p_limit = NULL;
	PROC_UNLOCK(p);
	lim_free(plim);

	tidhash_remove(td);

	/*
	 * Remove proc from allproc queue and pidhash chain.
	 * Place onto zombproc.  Unlink from parent's child list.
	 */
	sx_xlock(&allproc_lock);
	LIST_REMOVE(p, p_list);
	LIST_INSERT_HEAD(&zombproc, p, p_list);
	LIST_REMOVE(p, p_hash);
	sx_xunlock(&allproc_lock);

	/*
	 * Call machine-dependent code to release any
	 * machine-dependent resources other than the address space.
	 * The address space is released by "vmspace_exitfree(p)" in
	 * vm_waitproc().
	 */
	cpu_exit(td);

	WITNESS_WARN(WARN_PANIC, NULL, "process (pid %d) exiting", p->p_pid);

	/*
	 * Reparent all of our children to init.
	 */
	sx_xlock(&proctree_lock);
	q = LIST_FIRST(&p->p_children);
	if (q != NULL)		/* only need this if any child is S_ZOMB */
		wakeup(initproc);
	for (; q != NULL; q = nq) {
		nq = LIST_NEXT(q, p_sibling);
		PROC_LOCK(q);
		proc_reparent(q, initproc);
		q->p_sigparent = SIGCHLD;
		/*
		 * Traced processes are killed
		 * since their existence means someone is screwing up.
		 */
		if (q->p_flag & P_TRACED) {
			struct thread *temp;

			/*
			 * Since q was found on our children list, the
			 * proc_reparent() call moved q to the orphan
			 * list due to present P_TRACED flag. Clear
			 * orphan link for q now while q is locked.
			 */
			clear_orphan(q);
			q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
			FOREACH_THREAD_IN_PROC(q, temp)
				temp->td_dbgflags &= ~TDB_SUSPEND;
			kern_psignal(q, SIGKILL);
		}
		PROC_UNLOCK(q);
	}

	/*
	 * Also get rid of our orphans.
	 */
	while ((q = LIST_FIRST(&p->p_orphans)) != NULL) {
		PROC_LOCK(q);
		clear_orphan(q);
		PROC_UNLOCK(q);
	}

	/* Save exit status. */
	PROC_LOCK(p);
	p->p_xthread = td;

	/* Tell the prison that we are gone. */
	prison_proc_free(p->p_ucred->cr_prison);

#ifdef KDTRACE_HOOKS
	/*
	 * Tell the DTrace fasttrap provider about the exit if it
	 * has declared an interest.
	 */
	if (dtrace_fasttrap_exit)
		dtrace_fasttrap_exit(p);
#endif

	/*
	 * Notify interested parties of our demise.
	 */
	KNOTE_LOCKED(&p->p_klist, NOTE_EXIT);

#ifdef KDTRACE_HOOKS
	int reason = CLD_EXITED;
	if (WCOREDUMP(rv))
		reason = CLD_DUMPED;
	else if (WIFSIGNALED(rv))
		reason = CLD_KILLED;
	SDT_PROBE(proc, kernel, , exit, reason, 0, 0, 0, 0);
#endif

	/*
	 * Just delete all entries in the p_klist. At this point we won't
	 * report any more events, and there are nasty race conditions that
	 * can beat us if we don't.
	 */
	knlist_clear(&p->p_klist, 1);

	/*
	 * If this is a process with a descriptor, we may not need to deliver
	 * a signal to the parent.  proctree_lock is held over
	 * procdesc_exit() to serialize concurrent calls to close() and
	 * exit().
	 */
#ifdef PROCDESC
	if (p->p_procdesc == NULL || procdesc_exit(p)) {
#endif
		/*
		 * Notify parent that we're gone.  If parent has the
		 * PS_NOCLDWAIT flag set, or if the handler is set to SIG_IGN,
		 * notify process 1 instead (and hope it will handle this
		 * situation).
		 */
		PROC_LOCK(p->p_pptr);
		mtx_lock(&p->p_pptr->p_sigacts->ps_mtx);
		if (p->p_pptr->p_sigacts->ps_flag &
		    (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
			struct proc *pp;

			mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
			pp = p->p_pptr;
			PROC_UNLOCK(pp);
			proc_reparent(p, initproc);
			p->p_sigparent = SIGCHLD;
			PROC_LOCK(p->p_pptr);

			/*
			 * Notify parent, so in case he was wait(2)ing or
			 * executing waitpid(2) with our pid, he will
			 * continue.
			 */
			wakeup(pp);
		} else
			mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);

		if (p->p_pptr == initproc)
			kern_psignal(p->p_pptr, SIGCHLD);
		else if (p->p_sigparent != 0) {
			if (p->p_sigparent == SIGCHLD)
				childproc_exited(p);
			else	/* LINUX thread */
				kern_psignal(p->p_pptr, p->p_sigparent);
		}
#ifdef PROCDESC
	} else
		PROC_LOCK(p->p_pptr);
#endif
	sx_xunlock(&proctree_lock);

	/*
	 * The state PRS_ZOMBIE prevents other proesses from sending
	 * signal to the process, to avoid memory leak, we free memory
	 * for signal queue at the time when the state is set.
	 */
	sigqueue_flush(&p->p_sigqueue);
	sigqueue_flush(&td->td_sigqueue);

	/*
	 * We have to wait until after acquiring all locks before
	 * changing p_state.  We need to avoid all possible context
	 * switches (including ones from blocking on a mutex) while
	 * marked as a zombie.  We also have to set the zombie state
	 * before we release the parent process' proc lock to avoid
	 * a lost wakeup.  So, we first call wakeup, then we grab the
	 * sched lock, update the state, and release the parent process'
	 * proc lock.
	 */
	wakeup(p->p_pptr);
	cv_broadcast(&p->p_pwait);
	sched_exit(p->p_pptr, td);
	PROC_SLOCK(p);
	p->p_state = PRS_ZOMBIE;
	PROC_UNLOCK(p->p_pptr);

	/*
	 * Hopefully no one will try to deliver a signal to the process this
	 * late in the game.
	 */
	knlist_destroy(&p->p_klist);

	/*
	 * Save our children's rusage information in our exit rusage.
	 */
	ruadd(&p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux);

	/*
	 * Make sure the scheduler takes this thread out of its tables etc.
	 * This will also release this thread's reference to the ucred.
	 * Other thread parts to release include pcb bits and such.
	 */
	thread_exit();
}
示例#22
0
static int
debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
    int i;
    const char **newArgs;
    int errCode = 0;
    uio_StdioAccessHandle **handles;
    uio_DirHandle *tempDir;

    if (argc < 2) {
        fprintf(debugContext->err, "Invalid number of arguments.\n");
        return 1;
    }

    tempDir = uio_openDirRelative(debugContext->cwd, "/tmp", 0);
    if (tempDir == 0) {
        fprintf(debugContext->err, "Could not open temp dir: %s.\n",
                strerror(errno));
        return 1;
    }

    newArgs = uio_malloc(argc * sizeof (char *));
    newArgs[0] = argv[1];
    handles = uio_malloc(argc * sizeof (uio_StdioAccessHandle *));
    handles[0] = NULL;

    for (i = 2; i < argc; i++) {
#if 0
        if (argv[i][0] == '-') {
            // Don't try to parse arguments that start with '-'.
            // They are probably option flags.
            newArgs[i - 1] = argv[i];
        }
#endif
        handles[i - 1] = uio_getStdioAccess(debugContext->cwd, argv[i],
                                            O_RDONLY, tempDir);
        if (handles[i - 1] == NULL) {
            if (errno == ENOENT) {
                // No match; we keep what's typed literally.
                newArgs[i - 1] = argv[i];
                continue;
            }

            // error
            fprintf(debugContext->err,
                    "Cannot execute: Cannot get stdio access to %s: %s.\n",
                    argv[i], strerror(errno));
            errCode = 1;
            argc = i + 1;
            goto err;
        }

        newArgs[i - 1] = uio_StdioAccessHandle_getPath(handles[i - 1]);
    }
    newArgs[argc - 1] = NULL;

    fprintf(debugContext->err, "Executing: %s", newArgs[0]);
    for (i = 1; i < argc - 1; i++)
        fprintf(debugContext->err, " %s", newArgs[i]);
    fprintf(debugContext->err, "\n");

#if defined(__unix__) && !defined(_WIN32_WCE)
    {
        pid_t pid;

        pid = fork();
        switch (pid) {
        case -1:
            fprintf(debugContext->err, "Error: fork() failed: %s.\n",
                    strerror(errno));
            break;
        case 0:
            // child
            execvp(newArgs[0], (char * const *) newArgs);
            fprintf(debugContext->err, "Error: execvp() failed: %s.\n",
                    strerror(errno));
            _exit(EXIT_FAILURE);
            break;
        default: {
            // parent
            int status;
            pid_t retVal;

            while (1) {
                retVal = waitpid(pid, &status, 0);
                if (retVal != -1)
                    break;
                if (errno != EINTR) {
                    fprintf(debugContext->err, "Error: waitpid() "
                            "failed: %s\n", strerror(errno));
                    break;
                }
            }
            if (retVal == -1)
                break;

            if (WIFEXITED(status)) {
                fprintf(debugContext->err, "Exit status: %d\n",
                        WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) {
                fprintf(debugContext->err, "Terminated on signal %d.\n",
                        WTERMSIG(status));
            } else {
                fprintf(debugContext->err, "Error: weird exit status.\n");
            }
            break;
        }
        }
    }
#else
    fprintf(debugContext->err, "Cannot execute: not supported on this "
            "platform.\n");
#endif

err:
    for (i = 1; i < argc - 1; i++) {
        if (handles[i] != NULL)
            uio_releaseStdioAccess(handles[i]);
    }
    uio_free(handles);
    uio_free((void *) newArgs);
    uio_closeDir(tempDir);

    return errCode;
}
示例#23
0
/*
 * get_child_exit: This looks for dead child processes of the client.
 * There are two main sources of dead children:  Either an /exec'd process
 * has exited, or the client has attempted to fork() off a helper process
 * (such as wserv or gzip) and that process has choked on itself.
 *
 * When SIGCHLD is recieved, the global variable 'dead_children_processes'
 * is incremented.  When this function is called, we go through and call
 * waitpid() on all of the outstanding zombies, conditionally stopping when
 * we reach a specific wanted sub-process.
 *
 * If you want to stop reaping children when a specific subprocess is 
 * reached, specify the process in 'wanted'.  If all youre doing is cleaning
 * up after zombies and /exec's, then 'wanted' should be -1.
 */
int 		get_child_exit (pid_t wanted)
{
	Process	*proc;
	pid_t	pid;
	int	status, i;

	/*
	 * Iterate until we've reaped all of the dead processes
	 * or we've found the one asked for.
	 */
	if (dead_children_processes)
	{
	    block_signal(SIGCHLD);
	    while ((pid = waitpid(wanted, &status, WNOHANG)) > 0)
	    {
		/*
		 * First thing we do is look to see if the process we're
		 * working on is the one that was asked for.  If it is,
		 * then we get its exit status information and return it.
		 */
		if (wanted != -1 && pid == wanted)
		{
		        unblock_signal(SIGCHLD);

			if (WIFEXITED(status))
				return WEXITSTATUS(status);
			if (WIFSTOPPED(status))
				return -(WSTOPSIG(status));
			if (WIFSIGNALED(status)) 
				return -(WTERMSIG(status));
		}

		/*
		 * If it wasnt the process asked for, then we've probably
		 * stumbled across a dead /exec'd process.  Look for the
		 * corresponding child process, and mark it as being dead.
		 */
		else
		{
			for (i = 0; i < process_list_size; i++)
			{
				proc = process_list[i];
				if (proc && proc->pid == pid)
				{
					proc->exited = 1;
					proc->termsig = WTERMSIG(status);
					proc->retcode = WEXITSTATUS(status);
					break;
				}
			}
		}
	    }
	    dead_children_processes = 0;
	    unblock_signal(SIGCHLD);
	}

	/*
	 * Now we may have reaped some /exec'd processes that were previously
	 * dumb and have now exited.  So we call cleanup_dead_processes() to 
	 * find and delete any such processes.
	 */
	cleanup_dead_processes();

	/*
	 * If 'wanted' is not -1, then we didnt find that process, and
	 * if 'wanted' is -1, then you should ignore the retval anyhow. ;-)
	 */
	return -1;
}
示例#24
0
/*
 * Checks whether key is allowed in output of command.
 * returns 1 if the key is allowed or 0 otherwise.
 */
static int
user_key_command_allowed2(struct passwd *user_pw, Key *key)
{
	FILE *f;
	int ok, found_key = 0;
	struct passwd *pw;
	struct stat st;
	int status, devnull, p[2], i;
	pid_t pid;
	char *username, errmsg[512];

	if (options.authorized_keys_command == NULL ||
	    options.authorized_keys_command[0] != '/')
		return 0;

	if (options.authorized_keys_command_user == NULL) {
		error("No user for AuthorizedKeysCommand specified, skipping");
		return 0;
	}

	username = percent_expand(options.authorized_keys_command_user,
	    "u", user_pw->pw_name, (char *)NULL);
	pw = getpwnam(username);
	if (pw == NULL) {
		error("AuthorizedKeysCommandUser \"%s\" not found: %s",
		    username, strerror(errno));
		free(username);
		return 0;
	}
	free(username);

	temporarily_use_uid(pw);

	if (stat(options.authorized_keys_command, &st) < 0) {
		error("Could not stat AuthorizedKeysCommand \"%s\": %s",
		    options.authorized_keys_command, strerror(errno));
		goto out;
	}
	if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
	    errmsg, sizeof(errmsg)) != 0) {
		error("Unsafe AuthorizedKeysCommand: %s", errmsg);
		goto out;
	}

	if (pipe(p) != 0) {
		error("%s: pipe: %s", __func__, strerror(errno));
		goto out;
	}

	debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
	    options.authorized_keys_command, user_pw->pw_name, pw->pw_name);

	/*
	 * Don't want to call this in the child, where it can fatal() and
	 * run cleanup_exit() code.
	 */
	restore_uid();

	switch ((pid = fork())) {
	case -1: /* error */
		error("%s: fork: %s", __func__, strerror(errno));
		close(p[0]);
		close(p[1]);
		return 0;
	case 0: /* child */
		for (i = 0; i < NSIG; i++)
			signal(i, SIG_DFL);

		if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
			error("%s: open %s: %s", __func__, _PATH_DEVNULL,
			    strerror(errno));
			_exit(1);
		}
		/* Keep stderr around a while longer to catch errors */
		if (dup2(devnull, STDIN_FILENO) == -1 ||
		    dup2(p[1], STDOUT_FILENO) == -1) {
			error("%s: dup2: %s", __func__, strerror(errno));
			_exit(1);
		}
		closefrom(STDERR_FILENO + 1);

		/* Don't use permanently_set_uid() here to avoid fatal() */
		if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
			error("setresgid %u: %s", (u_int)pw->pw_gid,
			    strerror(errno));
			_exit(1);
		}
		if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
			error("setresuid %u: %s", (u_int)pw->pw_uid,
			    strerror(errno));
			_exit(1);
		}
		/* stdin is pointed to /dev/null at this point */
		if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
			error("%s: dup2: %s", __func__, strerror(errno));
			_exit(1);
		}

		execl(options.authorized_keys_command,
		    options.authorized_keys_command, user_pw->pw_name, NULL);

		error("AuthorizedKeysCommand %s exec failed: %s",
		    options.authorized_keys_command, strerror(errno));
		_exit(127);
	default: /* parent */
		break;
	}

	temporarily_use_uid(pw);

	close(p[1]);
	if ((f = fdopen(p[0], "r")) == NULL) {
		error("%s: fdopen: %s", __func__, strerror(errno));
		close(p[0]);
		/* Don't leave zombie child */
		kill(pid, SIGTERM);
		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
			;
		goto out;
	}
	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
	fclose(f);

	while (waitpid(pid, &status, 0) == -1) {
		if (errno != EINTR) {
			error("%s: waitpid: %s", __func__, strerror(errno));
			goto out;
		}
	}
	if (WIFSIGNALED(status)) {
		error("AuthorizedKeysCommand %s exited on signal %d",
		    options.authorized_keys_command, WTERMSIG(status));
		goto out;
	} else if (WEXITSTATUS(status) != 0) {
		error("AuthorizedKeysCommand %s returned status %d",
		    options.authorized_keys_command, WEXITSTATUS(status));
		goto out;
	}
	found_key = ok;
 out:
	restore_uid();
	return found_key;
}
示例#25
0
/**
   Handle status update for child \c pid. This function is called by
   the signal handler, so it mustn't use malloc or any such hitech
   nonsense.

   \param pid the pid of the process whose status changes
   \param status the status as returned by wait
*/
static void handle_child_status( pid_t pid, int status )
{
	bool found_proc = false;
	const job_t *j=0;
	process_t *p=0;
//	char mess[MESS_SIZE];	
	/*
	  snprintf( mess, 
	  MESS_SIZE,
	  "Process %d\n",
	  (int) pid );
	  write( 2, mess, strlen(mess ));
	*/

    job_iterator_t jobs;
	while (! found_proc && (j = jobs.next()))
	{
		process_t *prev=0;
		for( p=j->first_process; p; p=p->next )
		{
			if( pid == p->pid )
			{
/*				snprintf( mess,
  MESS_SIZE,
  "Process %d is %ls from job %ls\n",
  (int) pid, p->actual_cmd, j->command );
  write( 2, mess, strlen(mess ));
*/		
				
				mark_process_status ( j, p, status);
				if( p->completed && prev != 0  )
				{
					if( !prev->completed && prev->pid)
					{
						/*					snprintf( mess,
						  MESS_SIZE,
						  "Kill previously uncompleted process %ls (%d)\n",
						  prev->actual_cmd, 
						  prev->pid );
						  write( 2, mess, strlen(mess ));
						*/
						kill(prev->pid,SIGPIPE);
					}
				}
				found_proc = true;
				break;
			}
			prev = p;
		}
	}


	if( WIFSIGNALED( status ) && 
		( WTERMSIG(status)==SIGINT  || 
		  WTERMSIG(status)==SIGQUIT ) )
	{
		if( !is_interactive_session )
		{			
			struct sigaction act;
			sigemptyset( & act.sa_mask );
			act.sa_flags=0;	
			act.sa_handler=SIG_DFL;
			sigaction( SIGINT, &act, 0 );
			sigaction( SIGQUIT, &act, 0 );
			kill( getpid(), WTERMSIG(status) );
		}
		else
		{
            /* In an interactive session, tell the principal parser to skip all blocks we're executing so control-C returns control to the user. */
			if( p && found_proc )
			{
                parser_t::skip_all_blocks();
			}			
		}
	}
		
	if( !found_proc )
	{
		/* 
		   A child we lost track of?
		   
		   There have been bugs in both subshell handling and in
		   builtin handling that have caused this previously...
		*/
/*		snprintf( mess, 
  MESS_SIZE,
  "Process %d not found by %d\n",
  (int) pid, (int)getpid() );

  write( 2, mess, strlen(mess ));
*/
	}	
	return;
}
示例#26
0
void * threaded (void * arg)
{
    int ret = 0;

#if VERBOSE > 4
    output("Thread %i starting...\n", sc);
#endif

    /* Alternate stack test */
    if (scenarii[sc].bottom != NULL)
    {
#ifdef WITHOUT_XOPEN
        output("Unable to test the alternate stack feature; need an integer pointer cast\n");
#else
        intptr_t stack_start, stack_end, current_pos;

        stack_start = (intptr_t) scenarii[sc].bottom;
        stack_end = stack_start + (intptr_t)sysconf(_SC_THREAD_STACK_MIN);
        current_pos = (intptr_t)&ret;

#if VERBOSE > 2
        output("Stack bottom: %p\n", scenarii[sc].bottom);
        output("Stack end   : %p (stack is 0x%lx bytes)\n", (void *)stack_end, stack_end - stack_start);
        output("Current pos : %p\n", &ret);
#endif
        if ((stack_start > current_pos) || (current_pos > stack_end))
        {
            FAILED("The specified stack was not used.\n");
        }

#endif // WITHOUT_XOPEN
    }


    /* Guard size test */
    if ((scenarii[sc].bottom == NULL)  /* no alternative stack was specified */
            && (scenarii[sc].guard == 2)   /* guard area size is 1 memory page */
            && (scenarii[sc].altsize == 1))/* We know the stack size */
    {
        pid_t child, ctrl;
        int status;

        child=fork(); /* We'll test the feature in another process as this test may segfault */

        if (child == -1)  {
            UNRESOLVED(errno, "Failed to fork()");
        }

        if (child != 0) /* father */
        {
            /* Just wait for the child and check its return value */
            ctrl = waitpid(child, &status, 0);
            if (ctrl != child)  {
                UNRESOLVED(errno, "Failed to wait for process termination");
            }

            if (WIFEXITED(status)) /* The process exited */
            {
                if (WEXITSTATUS(status) == 0)
                {
                    FAILED("Overflow into the guard area did not fail");
                }
                if (WEXITSTATUS(status) == PTS_UNRESOLVED)
                {
                    UNRESOLVED(-1, "The child process returned unresolved status");
                }
#if VERBOSE > 4
                else
                {
                    output("The child process returned: %i\n", WEXITSTATUS(status));
                }
            }
            else
            {
                output("The child process did not returned\n");
                if (WIFSIGNALED(status))
                    output("It was killed with signal %i\n", WTERMSIG(status));
                else
                    output("neither was it killed. (status = %i)\n", status);
#endif
            }
        }

        if (child == 0) /* this is the new process */
        {
            pthread_t th;

            ret = pthread_create(&th, &scenarii[sc].ta, overflow, NULL);  /* Create a new thread with the same attributes */
            if (ret != 0) {
                UNRESOLVED(ret, "Unable to create another thread with the same attributes in the new process");
            }

            if (scenarii[sc].detached == 0)
            {
                ret = pthread_join(th, NULL);
                if (ret != 0)  {
                    UNRESOLVED(ret, "Unable to join a thread");
                }
            }
            else
            {
                /* Just wait for the thread to terminate */
                do {
                    ret = sem_wait(&scenarii[sc].sem);
                }
                while ((ret == -1) && (errno == EINTR));
                if (ret == -1)  {
                    UNRESOLVED(errno, "Failed to wait for the semaphore");
                }
            }

            /* Terminate the child process here */
            exit(0);
        }
    }


    /* Post the semaphore to unlock the main thread in case of a detached thread */
    do {
        ret = sem_post(&scenarii[sc].sem);
    }
    while ((ret == -1) && (errno == EINTR));
    if (ret == -1)  {
        UNRESOLVED(errno, "Failed to post the semaphore");
    }

    return arg;
}
示例#27
0
i4
PCreap_withThisPid(int targetPid)
{
#ifdef xCL_001_WAIT_UNION
    union wait wait_status;
#else
    int	wait_status;
#endif

    i4	proc_stat;
    i4  sys_stat;

    register PIDQUE	*sqp;		/* search queue pointer */
    register PID	pid;
    register STATUS	rval;

    TYPESIG (*inthandler)();
    TYPESIG (*quithandler)();

    /* 
    ** If the Pidq doesn't exist, no point waiting for the child 
    ** since we don't care anyway.
    */
    if(Pidq_init == FALSE)
	return( -1 );	

    /*
    ** Disable the SIGINT and SIGQUIT, and save their old actions.
    ** EXinterrupt(EX_OFF) now latches incoming keyboard interrupts,
    ** rather than discarding them; we need to actually turn the
    ** signal handling off.
    */
    inthandler = signal(SIGINT, SIG_IGN);
    quithandler = signal(SIGQUIT, SIG_IGN);

    /*
    ** Set a default result-code
    ** - As above return code, meaning "Child does not exist"
    */
    pid = -1;

    for (sqp = (PIDQUE *) Pidq.q_next;
                sqp != (PIDQUE *) &Pidq;
                sqp = (PIDQUE *) sqp->pidq.q_next )
    {
        /*
        ** Are we looking for a specific child to checkup on ?
        */
        if (targetPid != -1)
        {
            /*
            ** Pick out that child by stepping right over the others.
            */
            if (targetPid != sqp->pid)
                continue; /** the for loop **/

            /*
            ** The child does exist, so change the default result-code.
            ** - Now means "Child state changed from executable"
            */
            pid = targetPid;
        }

        /*
        ** Still executing this child ?
        */
        if ( sqp->stat == PC_WT_EXEC )
        {
           /*
           ** Loop until no error (-1) attempting to read status of this pid
           ** - A zero result here now means "pid reports no state change"
           ** - WNOHANG is important, this call will not block if child
           **   still running ... so we may use routine a a polling agent.
           */
           while (((pid = waitpid ( sqp->pid, (int *)&wait_status, WNOHANG)) == -1) && (errno == EINTR));

            if ( pid == sqp->pid )
            {
                /* error pid needs no special handling; it falls on the floor */

# ifdef xCL_001_WAIT_UNION
               proc_stat = wait_status.w_retcode;
               sys_stat = wait_status.w_status & ~(proc_stat);
# else
# ifdef xCL_USE_WAIT_MACROS
		if ( WIFEXITED( wait_status ) )
		{
		   /* process exited, set PC status based on exit value */
		   proc_stat = WEXITSTATUS( wait_status );
 		   sqp->stat = proc_stat == 0 ?
				OK : PC_WT_BAD ;
		   break;
		}
		else if ( WIFSIGNALED( wait_status ) )
		{
		    /* process terminated by signal */
		    sqp->stat = PC_WT_TERM;
		    break;
		}
		else if ( WIFSTOPPED( wait_status ) )
		{
		    /* process interrupted by signal */
		    sqp->stat = PC_WT_INTR;
		    break;
		}
		else
# endif
		{
		    proc_stat = wait_status & 0377;
		    sys_stat = wait_status & ~(proc_stat);
		}
# endif
    /*
    ** Map the status of the dead child to a PC_WT_code.
    */

               sqp->stat = proc_stat == 0 ? OK : sys_stat == 0 ? PC_WT_TERM : PC_WT_BAD;
               break;
            }
        }

        /*
        ** Were we were targetting a particular pid ?
        */
        if (targetPid != -1)
        {
	    /* 
	    ** Break  out of for-loop 
	    */
            break;
        }
    }

    /* reset interrupt and quit signals */

    (void) signal(SIGINT, inthandler);
    (void) signal(SIGQUIT, quithandler);

    return( pid );
}
示例#28
0
/* some of this code is based on /usr/bin/time source code */
void
print_stats(struct timeval *start, struct timeval *end,
            struct rusage *ru, int status)
{
    unsigned long r;            /* Elapsed real milliseconds.  */
    unsigned long v;            /* Elapsed virtual (CPU) milliseconds.  */
    end->tv_sec -= start->tv_sec;
    if (end->tv_usec < start->tv_usec) {
        /* Manually carry a one from the seconds field.  */
        end->tv_usec += 1000000;
        --end->tv_sec;
    }
    end->tv_usec -= start->tv_usec;

    if (WIFSTOPPED (status)) {
        fprintf(FP, "Command stopped by signal %d\n",
                WSTOPSIG (status));
    } else if (WIFSIGNALED (status)) {
        fprintf(FP, "Command terminated by signal %d\n",
                WTERMSIG (status));
    } else if (WIFEXITED (status) && WEXITSTATUS (status)) {
        fprintf(FP, "Command exited with non-zero status %d\n",
                WEXITSTATUS (status));
    }

    /* Convert all times to milliseconds.  Occasionally, one of these values
       comes out as zero.  Dividing by zero causes problems, so we first
       check the time value.  If it is zero, then we take `evasive action'
       instead of calculating a value.  */
    
    r = end->tv_sec * 1000 + end->tv_usec / 1000;
    
    v = ru->ru_utime.tv_sec * 1000 + ru->ru_utime.TV_MSEC +
        ru->ru_stime.tv_sec * 1000 + ru->ru_stime.TV_MSEC;

    /* Elapsed real (wall clock) time.  */
    if (end->tv_sec >= 3600) {  /* One hour -> h:m:s.  */
        fprintf(FP, "%ld:%02ld:%02ldelapsed ",
                 end->tv_sec / 3600,
                 (end->tv_sec % 3600) / 60,
                 end->tv_sec % 60);
    } else {
        fprintf(FP, "%ld:%02ld.%02ldelapsed ",  /* -> m:s.  */
                 end->tv_sec / 60,
                 end->tv_sec % 60,
                 end->tv_usec / 10000);
    }
    /* % cpu is (total cpu time)/(elapsed time).  */
    if (r > 0)
        fprintf(FP, "%lu%%CPU ", (v * 100 / r));
    else
        fprintf(FP, "?%%CPU ");
    fprintf(FP, "%ld.%02lduser ",
            ru->ru_utime.tv_sec, ru->ru_utime.TV_MSEC / 10);
    fprintf(FP, "%ld.%02ldsystem ",
            ru->ru_stime.tv_sec, ru->ru_stime.TV_MSEC / 10);
    fprintf(FP, "(%ldmajor+%ldminor)pagefaults %ldswaps\n",
            ru->ru_majflt,/* Major page faults.  */
            ru->ru_minflt,/* Minor page faults.  */
            ru->ru_nswap); /* times swapped out */
    fprintf(FP, "(%lu tot, %lu RSS, %lu data, %lu stk, %lu exe, %lu lib)k\n",
            vmstats.VmSize, vmstats.VmRSS, vmstats.VmData,
            vmstats.VmStk, vmstats.VmExe, vmstats.VmLib);

#if VERBOSE
    fprintf(FP, "Memory usage:\n");
    fprintf(FP, "\tVmSize: %d kB\n", vmstats.VmSize);
    fprintf(FP, "\tVmLck: %d kB\n", vmstats.VmLck);
    fprintf(FP, "\tVmRSS: %d kB\n", vmstats.VmRSS);
    fprintf(FP, "\tVmData: %d kB\n", vmstats.VmData);
    fprintf(FP, "\tVmStk: %d kB\n", vmstats.VmStk);
    fprintf(FP, "\tVmExe: %d kB\n", vmstats.VmExe);
    fprintf(FP, "\tVmLib: %d kB\n", vmstats.VmLib);
#endif
}
示例#29
0
int
main(int argc, char **argv) {
	int			c;
	int			tnum;
	int			subprocs;
	pid_t			deadpid;
	int			status;
	int			len;
	isc_boolean_t		first;
	testspec_t		*pts;
	struct sigaction	sa;

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;
	first = ISC_TRUE;
	subprocs = 1;
	T_timeout = T_TCTOUT;

	/*
	 * -a option is now default.
	 */
	memset(T_tvec, 0xff, sizeof(T_tvec));

	/*
	 * Parse args.
	 */
	while ((c = isc_commandline_parse(argc, argv, ":at:c:d:n:huxq:b:"))
	       != -1) {
		if (c == 'a') {
			/*
			 * Flag all tests to be run.
			 */
			memset(T_tvec, 0xff, sizeof(T_tvec));
		}
		else if (c == 'b') {
			T_dir = isc_commandline_argument;
		}
		else if (c == 't') {
			tnum = atoi(isc_commandline_argument);
			if ((tnum > 0) && (tnum < T_MAXTESTS)) {
				if (first) {
					/*
					 * Turn off effect of -a default
					 * and allow multiple -t and -n
					 * options.
					 */
					memset(T_tvec, 0, sizeof(T_tvec));
					first = ISC_FALSE;
				}
				/*
				 * Flag test tnum to be run.
				 */
				tnum -= 1;
				T_tvec[tnum / 8] |= (0x01 << (tnum % 8));
			}
		}
		else if (c == 'c') {
			T_config = isc_commandline_argument;
		}
		else if (c == 'd') {
			T_debug = atoi(isc_commandline_argument);
		}
		else if (c == 'n') {
			pts = &T_testlist[0];
			tnum = 0;
			while (pts->pfv != NULL) {
				if (! strcmp(pts->func_name,
					     isc_commandline_argument)) {
					if (first) {
						memset(T_tvec, 0,
						       sizeof(T_tvec));
						first = ISC_FALSE;
					}
					T_tvec[tnum/8] |= (0x01 << (tnum%8));
					break;
				}
				++pts;
				++tnum;
			}
			if (pts->pfv == NULL) {
				fprintf(stderr, "no such test %s\n",
					isc_commandline_argument);
				exit(1);
			}
		}
		else if (c == 'h') {
			printhelp();
			exit(0);
		}
		else if (c == 'u') {
			printusage();
			exit(0);
		}
		else if (c == 'x') {
			subprocs = 0;
		}
		else if (c == 'q') {
			T_timeout = atoi(isc_commandline_argument);
		}
		else if (c == ':') {
			fprintf(stderr, "Option -%c requires an argument\n",
						isc_commandline_option);
			exit(1);
		}
		else if (c == '?') {
			fprintf(stderr, "Unrecognized option -%c\n",
				isc_commandline_option);
			exit(1);
		}
	}

	/*
	 * Set cwd.
	 */

	if (T_dir != NULL && chdir(T_dir) != 0) {
		fprintf(stderr, "chdir %s failed\n", T_dir);
		exit(1);
	}

	/*
	 * We don't want buffered output.
	 */

	(void)setbuf(stdout, NULL);
	(void)setbuf(stderr, NULL);

	/*
	 * Setup signals.
	 */

	sa.sa_flags = 0;
	sigfillset(&sa.sa_mask);

	sa.sa_handler = t_sighandler;
	(void)sigaction(SIGINT,  &sa, NULL);
	(void)sigaction(SIGALRM, &sa, NULL);

	/*
	 * Output start stanza to journal.
	 */

	snprintf(T_buf, sizeof(T_buf), "%s:", argv[0]);
	len = strlen(T_buf);
	(void) t_getdate(T_buf + len, T_BIGBUF - len);
	t_putinfo("S", T_buf);

	/*
	 * Setup the test environment using the config file.
	 */

	if (T_config == NULL)
		T_config = T_DEFAULT_CONFIG;

	t_initconf(T_config);
	if (T_debug)
		t_dumpconf(T_config);

	/*
	 * Now invoke all the test cases.
	 */

	tnum = 0;
	pts = &T_testlist[0];
	while (*pts->pfv != NULL) {
		if (T_tvec[tnum / 8] & (0x01 << (tnum % 8))) {
			if (subprocs) {
				T_pid = fork();
				if (T_pid == 0) {
					(*pts->pfv)();
					exit(0);
				} else if (T_pid > 0) {

					T_int = 0;
					sa.sa_handler = t_sighandler;
					(void)sigaction(SIGALRM, &sa, NULL);
					alarm(T_timeout);

					deadpid = (pid_t) -1;
					while (deadpid != T_pid) {
					    deadpid =
						    waitpid(T_pid, &status, 0);
					    if (deadpid == T_pid) {
						    if (WIFSIGNALED(status)) {
							if (WTERMSIG(status) ==
							    SIGTERM)
								t_info(
						  "the test case timed out\n");
							else
								t_info(
					 "the test case caused exception %d\n",
							     WTERMSIG(status));
							t_result(T_UNRESOLVED);
						    }
					    } else if ((deadpid == -1) &&
						       (errno == EINTR) &&
						       T_int) {
						    kill(T_pid, SIGTERM);
						    T_int = 0;
					    }
					    else if ((deadpid == -1) &&
						     ((errno == ECHILD) ||
						      (errno == ESRCH)))
						    break;
					}

					alarm(0);
					sa.sa_handler = SIG_IGN;
					(void)sigaction(SIGALRM, &sa, NULL);
				} else {
					t_info("fork failed, errno == %d\n",
					       errno);
					t_result(T_UNRESOLVED);
				}
			}
			else {
				(*pts->pfv)();
			}
		}
		++pts;
		++tnum;
	}

	snprintf(T_buf, sizeof(T_buf), "%s:", argv[0]);
	len = strlen(T_buf);
	(void) t_getdate(T_buf + len, T_BIGBUF - len);
	t_putinfo("E", T_buf);

	return(0);
}
示例#30
0
int main(int argc, char *argv[])
{
	pid_t child_pid;
	int child_exit_status;
	struct termios tty_attr;
	struct winsize window_size;
	int pty_master;

	/* for select */
	fd_set readfds;
	fd_set writefds;

	unsigned err_n_rpty = 0;
	unsigned err_n_wpty = 0;
	unsigned err_n_stdin = 0;
	unsigned err_n_stdout = 0;

	int done = 0;

	/* the ring buffers */
	char inbuf_mem[BUFSIZE];
	char outbuf_mem[BUFSIZE];
	struct ring_buffer inbuf;
	struct ring_buffer outbuf;
	rb_init(&inbuf, inbuf_mem, sizeof(inbuf_mem));
	rb_init(&outbuf, outbuf_mem, sizeof(outbuf_mem));

	if (argc == 1) {
		printf("usage: %s PROGRAM [ARGS]...\n", argv[0]);
		exit(1);
	}

	/* We need I/O calls to fail with EINTR on SIGCHLD... */
	if (signal(SIGCHLD, sigchld_handler) == SIG_ERR) {
		perror("signal(SIGCHLD,...)");
		exit(EX_OSERR);
	}

	if (isatty(STDIN_FILENO)) {
		/* get terminal parameters associated with stdout */
		if (tcgetattr(STDOUT_FILENO, &tty_attr) < 0) {
			perror("tcgetattr(stdout,...)");
			exit(EX_OSERR);
		}

		/* get window size */
		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window_size) < 0) {
			perror("ioctl(stdout,...)");
			exit(1);
		}

		child_pid = forkpty(&pty_master, NULL, &tty_attr, &window_size);
	} else { /* not interactive */
		child_pid = forkpty(&pty_master, NULL, NULL, NULL);
	}

	if (child_pid < 0) {
		perror("forkpty()");
		exit(EX_OSERR);
	}
	if (child_pid == 0) { /* in the child */
		struct termios s_tty_attr;
		if (tcgetattr(STDIN_FILENO, &s_tty_attr)) {
			perror("tcgetattr(stdin,...)");
			exit(EXIT_FAILURE);
		}
		/* Turn off echo */
		s_tty_attr.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
		/* Also turn of NL to CR?LF on output */
		s_tty_attr.c_oflag &= ~(ONLCR);
		if (tcsetattr(STDIN_FILENO, TCSANOW, &s_tty_attr)) {
			perror("tcsetattr(stdin,...)");
			exit(EXIT_FAILURE);
		}

		if (execvp(argv[1], argv + 1)) {
			perror("execvp()");
			exit(EXIT_FAILURE);
		}
	}

	/* Non blocking mode for all file descriptors. */
	setfd_nonblock(pty_master);
	setfd_nonblock(STDIN_FILENO);
	setfd_nonblock(STDOUT_FILENO);

	if (isatty(STDIN_FILENO)) {
		if (tty_semi_raw(STDIN_FILENO) < 0) {
			perror("tty_semi_raw(stdin)");
		}
		if (atexit(tty_atexit) < 0) {
			perror("atexit()");
		}
	}

	do {
		/* Accept events only on fds, that we can handle now. */
		int do_select = 0;
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		if (rb_space(&outbuf) > 0 && err_n_rpty < MAXRETR) {
			FD_SET(pty_master, &readfds);
			do_select = 1;
		}

		if (!rb_isempty(&inbuf) && err_n_wpty < MAXRETR) {
			FD_SET(pty_master, &writefds);
			do_select = 1;
		}

		if (rb_space(&inbuf) > 0 && err_n_stdin < MAXRETR) {
			FD_SET(STDIN_FILENO, &readfds);
			do_select = 1;
		}

		if (!rb_isempty(&outbuf) && err_n_stdout < MAXRETR) {
			FD_SET(STDOUT_FILENO, &writefds);
			do_select = 1;
		}

		if (!do_select) {
#ifdef DEBUG
			fprintf(stderr, "No I/O job for us, calling waitpid()...\n");
#endif
			while (waitpid(child_pid, &child_exit_status, 0) < 0)
			{
				/* nothing */
			}
			break;
		}

		errno = 0;
		int select_rc = select(pty_master + 1, &readfds, &writefds, NULL, NULL);
		if (select_rc < 0 && errno != EINTR) {
			perror("select()");
			exit(EX_IOERR);
		}
#ifdef DEBUG
		fprintf(stderr, "select() returned %d\n", select_rc);
#endif

		if (FD_ISSET(STDOUT_FILENO, &writefds)) {
#ifdef DEBUG
			fprintf(stderr, "stdout can be written\n");
#endif
			ssize_t n = rb_write(&outbuf, STDOUT_FILENO);
			if (n <= 0 && n != EINTR && n != EAGAIN)
				err_n_stdout++;
#ifdef DEBUG
			if (n >= 0)
				fprintf(stderr, "%d bytes written into stdout\n", n);
			else
				perror("write(stdout,...)");
#endif
		}

		if (FD_ISSET(pty_master, &writefds)) {
#ifdef DEBUG
			fprintf(stderr, "pty_master can be written\n");
#endif
			ssize_t n = rb_write(&inbuf, pty_master);
			if (n <= 0 && n != EINTR && n != EAGAIN)
				err_n_wpty++;
#ifdef DEBUG
			if (n >= 0)
				fprintf(stderr, "%d bytes written into pty_master\n", n);
			else
				perror("write(pty_master,...)");
#endif
		}

		if (FD_ISSET(STDIN_FILENO, &readfds)) {
#ifdef DEBUG
			fprintf(stderr, "stdin can be read\n");
#endif
			ssize_t n = rb_read(&inbuf, STDIN_FILENO);
			if (n <= 0 && n != EINTR && n != EAGAIN)
				err_n_stdin++;
#ifdef DEBUG
			if (n >= 0)
				fprintf(stderr, "%d bytes read from stdin\n", n);
			else
				perror("read(stdin,...)");
#endif
		}

		if (FD_ISSET(pty_master, &readfds)) {
#ifdef DEBUG
			fprintf(stderr, "pty_master can be read\n");
#endif
			ssize_t n = rb_read(&outbuf, pty_master);
			if (n <= 0 && n != EINTR && n != EAGAIN)
				err_n_rpty++;
#ifdef DEBUG
			if (n >= 0)
				fprintf(stderr, "%d bytes read from pty_master\n", n);
			else
				perror("read(pty_master,...)");
#endif
		}

		if (!done && waitpid(child_pid, &child_exit_status, WNOHANG) > 0)
			done = 1;

	} while (!done
		|| !(rb_isempty(&inbuf) || err_n_wpty >= MAXRETR)
		|| !(rb_isempty(&outbuf) || err_n_stdout >= MAXRETR));

#ifdef DEBUG
	fprintf(stderr, "inbuf: %u bytes left, outbuf: %u bytes left\n", inbuf.count, outbuf.count);
	fprintf(stderr, "err_n_rpty=%u, err_n_wpty=%u, err_n_stdin=%u, err_n_stdout=%u\n",
		err_n_rpty, err_n_wpty, err_n_stdin, err_n_stdout);
#endif

	if (WIFEXITED(child_exit_status))
		exit(WEXITSTATUS(child_exit_status));
	else if (WIFSIGNALED(child_exit_status))
		exit(128 + WTERMSIG(child_exit_status));

	exit(EXIT_FAILURE);
}