Chapter Contents |
Previous |
Next |
setpgid |
Portability: | POSIX.1 conforming |
SYNOPSIS | |
DESCRIPTION | |
RETURN VALUE | |
EXAMPLE | |
RELATED FUNCTIONS |
SYNOPSIS |
#include <unistd.h> int setpgid(pid_t pid, pid_t pgid);
DESCRIPTION |
setpgid
is used either to join an existing process group or to create
a new process group. The process specified by
pid
(or the calling process if
pid
is
0
) is joined
to the process group whose ID is
pgid
. If
pgid
is
not an existing process group ID, then
pgid
must equal
pid
or be
0
, in which case
a new process group with ID
pid
is created.
RETURN VALUE |
setpgid
returns a
0
if successful and a
-1
if not successful.
EXAMPLE |
A / \ / \ B C / \ / \ D E
Process D uses
setsid
to define itself as a new session. The other processes remain
in the session of A. The processes A and B comprise one process group, while
C and E comprise another. The
tcsetpgrp
function is used to cause C's process group to become the
foreground process group.
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <signal.h> char process = 'A'; /* the process ID of the running process */ void status(void) { /* display interesting process IDs */ printf("process %c: pid=%d, ppid=%d, pgid=%d, fg pgid=%dn", process, (int) getpid(), (int) getppid(), (int) getpgrp(), (int) tcgetpgrp(STDIN_FILENO)); } void erreport(char *func) { /* report an error and abort */ fprintf(stderr, "process %c ", process); perror(func); abort(); } void timeout(void) { /* wait up to 10 seconds, then quit */ unsigned waitfor = 20; while(waitfor) waitfor = sleep(waitfor); /* wait quietly ignoring signals for 20 seconds */ printf("process %c: Terminating after 20 seconds.n", process); exit(0); } void ttinhdlr(int signum) { printf("process %c: SIGTTIN detected.n", process); } void usr1hdlr(int signum) { /* null handler - allows parent to wait for init of child */ } void termhdlr(int signum) { printf("process %c: SIGTERM detected, terminating.n", process); exit(0); } void catchsig(void) { struct sigaction action; action.sa_handler = &ttinhdlr sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGTTIN, &action, 0)) erreport("sigaction"); action.sa_handler = &termhdlr if (sigaction(SIGTERM, &action, 0)) erreport("sigaction"); action.sa_handler = &usr1hdlr if (sigaction(SIGUSR1, &action, 0)) erreport("sigaction"); } pid_t createE(void) { /* fork and run process E - called by process C */ pid_t child; if ((child = fork()) != 0) return child; /* if running in parent, return child pid */ process = 'E'; catchsig(); status(); kill(getppid(), SIGUSR1); /* inform parent child is ready */ timeout(); return -1; /* should not occur */ } pid_t createC(void) { /* fork and run process C - called by process A */ pid_t child; sigset_t newmask, oldmask; if ((child = fork()) != 0) return child; /* if running in parent, return child pid */ process = 'C'; catchsig(); if (setpgid(0, 0) < 0) /* create new process group */ erreport("setpgid"); /* ignore SIGTTOU during tcsetpgrp */ signal(SIGTTOU, SIG_IGN); /* ignore SIGTTOU during tcsetpgrp */ signal(SIGTTOU, SIG_IGN); /* become foreground process group */ if (tcsetpgrp(STDIN_FILENO, getpid())) erreport("tcsetpgrp"); /* restore normal SIGTTOU handling */ signal(SIGTTOU, SIG_DFL); /* restore normal SIGTTOU handling */ signal(SIGTTOU, SIG_DFL); status(); if (createE() < 0) erreport("fork"); pause(); /* wait for SIGUSR1 from child */ sigemptyset(&newmask); sigaddset(&newmask, SIGTERM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); /* block SIGTERM until input read */ kill(getppid(), SIGUSR1); /* inform parent child is ready */ (void) getc(stdin); /* attempt to read from stdin (terminal) */ sigprocmask(SIG_SETMASK, &oldmask, 0); /* allow SIGTERM to interrupt now */ timeout(); return -1; /* should not occur */ } pid_t createD(void) { /* fork and run process D - called by process B */ pid_t child; if ((child = fork()) != 0) return child; /* if running in parent, return child pid */ process = 'D'; catchsig(); setsid(); /* start new session */ status(); kill(getppid(), SIGUSR1); /* inform parent child is ready */ timeout(); return -1; /* should not occur */ } pid_t createB(void) { /* fork and run process B - called by process A */ pid_t child; if ((child = fork()) != 0) return child; /* if running in parent, return child pid */ process = 'B'; catchsig(); status(); if (createD() < 0) erreport("fork"); pause(); /* wait for SIGUSR1 from child */ kill(getppid(), SIGUSR1); /* inform parent child is ready */ timeout(); return -1; /* should not occur */ } int main(void) { pid_t Cpid; /* process id for C */ pid_t Apid; /* process id for A */ Apid = getpid(); status(); printf("Enter carriage return to satisfy terminal read.n"); catchsig(); if (createB() < 0) erreport("fork"); pause(); /* wait for SIGUSR1 from child */ if ((Cpid = createC()) < 0) erreport("fork"); pause(); /* wait for SIGUSR1 from child */ while (tcgetpgrp(STDIN_FILENO) == getpid()) sleep(5); /* wait for foreground process group to change */ (void) getc(stdin); /* attempt to read from stdin (terminal) */ /* should generate SIGTTIN */ sleep(2); /* allow other processes to do their thing */ kill(-Cpid, SIGTERM);/* terminate processes C and E */ kill(0, SIGTERM); /* terminate processes A and B */ /* D will remain for some seconds */ }
RELATED FUNCTIONS |
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.