![]() 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.