|
|
1.1 ! root 1: .TH JOBS 3J ! 2: .UC 4 ! 3: .SH NAME ! 4: jobs \- summary of job control facilities ! 5: .SH SYNOPSIS ! 6: .nf ! 7: .B #include <sys/ioctl.h> ! 8: .B #include <signal.h> ! 9: .B #include <sys/vtimes.h> ! 10: .B #include <wait.h> ! 11: .PP ! 12: .B int fildes, signo; ! 13: .B short pid, pgrp; ! 14: .B union wait status; ! 15: .B struct vtimes vt; ! 16: .PP ! 17: .B ioctl(fildes, TIOCSPGRP, &pgrp) ! 18: .B ioctl(fildes, TIOCGPGRP, &pgrp) ! 19: .PP ! 20: .B setpgrp(pid, pgrp) ! 21: .B getpgrp(pid) ! 22: .B killpg(pgrp, signo) ! 23: .PP ! 24: .B sigset(signo, action) ! 25: .B sighold(signo) ! 26: .B sigrelse(signo) ! 27: .B sigpause(signo) ! 28: .B sigsys(signo, action) ! 29: .PP ! 30: .B wait3(&status, options, &vt) ! 31: .PP ! 32: .B cc ... \-ljobs ! 33: .fi ! 34: .SH DESCRIPTION ! 35: The facilities described here are used to support the job control implemented ! 36: in ! 37: .IR csh (1), ! 38: and may be used in other programs to provide similar facilities. ! 39: Because these facilities are not standard in UNIX and because the ! 40: signal mechanisms are also slightly different, the associated ! 41: routines are not in the standard C library, but rather in the \fB\-ljobs\fR ! 42: library. ! 43: .PP ! 44: For descriptions of the individual routines see the various sections listed ! 45: in \s-2SEE ALSO\s0 below. This section attempt only to place these facilities ! 46: in context, not to explain the semantics of the individual calls. ! 47: .PP ! 48: .B "Terminal arbitration mechanisms." ! 49: .PP ! 50: The job control mechanism works by associating with each process a number ! 51: called a ! 52: .I "process group"; ! 53: related processes (e.g. in a pipeline) are given the same process group. ! 54: The system assigns a single process group number to each terminal. ! 55: Processes running on a terminal are given read access to that terminal ! 56: only if they are in the same process group as that terminal. ! 57: .PP ! 58: Thus a command interpreter may start several jobs running in different ! 59: process groups and arbitrate access to the terminal by controlling which, ! 60: if any, of these processes is in the same process group as the terminal. ! 61: When a process which is not ! 62: in the process group of the terminal tries to read from the terminal, ! 63: all members of the process group of the process receive a SIGTTIN signal, ! 64: which normally then causes them to stop until they are continued ! 65: with a SIGCONT signal. ! 66: (See ! 67: .IR sigsys (2) ! 68: for a description of these signals; ! 69: .IR tty (4) ! 70: for a description of process groups.) ! 71: .PP ! 72: If a process which is not in the process group of the terminal ! 73: attempts to change the terminals mode, ! 74: the process group of that process is sent a SIGTTOU signal, causing ! 75: the process group to stop. ! 76: A similar mechanism is (optionally) available for output, causing ! 77: processes to block with SIGTTOU when they attempt to write to the terminal ! 78: while not in its process group; ! 79: this is controlled by the LTOSTOP bit in the tty mode ! 80: word, enabled by \*(lqstty tostop\*(rq and disabled (the default) ! 81: by \*(lqstty \-tostop.\*(rq ! 82: (The LTOSTOP bit is described in ! 83: .IR tty (4)). ! 84: .LP ! 85: .B "How the shell manipulates process groups." ! 86: .PP ! 87: A shell which is interactive first establishes its own process group ! 88: and a process group for the terminal; this prevents other processes ! 89: from being inadvertantly stopped while the terminal is under its control. ! 90: The shell then assigns each job it creates a distinct process group. ! 91: When a job is to be run in the foreground, ! 92: the shell gives the terminal to the process group of the job using ! 93: the TIOCSPGRP ioctl ! 94: (See ! 95: .IR ioctl (2) ! 96: and ! 97: .IR tty (4)). ! 98: When a job stops or completes, the shell reclaims the terminal ! 99: by resetting the terminals process group to that of the shell using ! 100: TIOCSPGRP again. ! 101: .PP ! 102: Shells which are running shell scripts or running non-interactively do ! 103: not manipulate process groups of jobs they create. Instead, they ! 104: leave the process group of sub-processes and the terminal unchanged. ! 105: This assures that if any sub-process they create blocks for terminal i/o, ! 106: the shell and all its sub-processes will be blocked ! 107: (since they are a single process group). ! 108: The first interactive parent of the non-interactive shell ! 109: can then be used to deal with the stoppage. ! 110: .PP ! 111: Processes which are orphans (whose parents have exited), and descendants ! 112: of these processes are protected by the system from stopping, since there ! 113: can be no interactive parent. Rather than blocking, reads from the ! 114: control terminal return end-of-file and writes to the control ! 115: terminal are permitted (i.e. LTOSTOP has no effect for these processes.) ! 116: Similarly processes which ignore or hold the SIGTTIN or SIGTTOU signal are not ! 117: sent these signals when accessing their control terminal; if they are not in the ! 118: process group of the control terminal reads simply return end-of-file. ! 119: Output and mode setting are also allowed. ! 120: .PP ! 121: Before a shell ! 122: .I suspends ! 123: itself, it places itself back in the process group in which it was ! 124: created, and then sends this original group a stopping signal, stopping ! 125: the shell and any other intermediate processes back to an interactive parent. ! 126: The shell also restores the process group of the terminal when it finishes, ! 127: as the process which then resumes would not necessarily be in control of ! 128: the terminal otherwise. ! 129: .PP ! 130: .B "Naive processes." ! 131: .PP ! 132: A process which does not alter the state of the terminal, ! 133: and which does no job control can invoke subprocesses normally ! 134: without worry. If such a process issues a ! 135: .IR system (3) ! 136: call and this command is then stopped, both of the processes will stop ! 137: together. Thus simple processes need not worry about job control, even ! 138: if they have \*(lqshell escapes\*(rq or invoke other processes. ! 139: .PP ! 140: .B "Processes which modify the terminal state." ! 141: .PP ! 142: When first setting the terminal into an unusual mode, the process ! 143: should check, with the stopping signals held, ! 144: that it is in the foreground. It should then change the state of the ! 145: terminal, and set the catches for SIGTTIN, SIGTTOU and SIGTSTP. ! 146: The following is a sample of the code that will be needed, assuming ! 147: that unit 2 is known to be a terminal. ! 148: .PP ! 149: .nf ! 150: .ft B ! 151: short tpgrp; ! 152: \&... ! 153: ! 154: retry: ! 155: sigset(SIGTSTP, SIG_HOLD); ! 156: sigset(SIGTTIN, SIG_HOLD); ! 157: sigset(SIGTTOU, SIG_HOLD); ! 158: if (ioctl(2, TIOCGPGRP, &tpgrp) != 0) ! 159: goto nottty; ! 160: if (tpgrp != getpgrp(0)) { /* not in foreground */ ! 161: sigset(SIGTTOU, SIG_DFL); ! 162: kill(0, SIGTTOU); ! 163: /* job stops here waiting for SIGCONT */ ! 164: goto retry; ! 165: } ! 166: \fI\&...save old terminal modes and set new modes\&...\fB ! 167: sigset(SIGTTIN, onstop); ! 168: sigset(SIGTTOU, onstop); ! 169: sigset(SIGTSTP, onstop); ! 170: .ft R ! 171: .fi ! 172: .PP ! 173: It is necessary to ignore SIGTSTP in this code because otherwise our process ! 174: could be moved from the foreground to the background in the middle of checking ! 175: if it is in the foreground. ! 176: The process holds all the stopping signals in this critical section so no other ! 177: process in our process group can mess us up by blocking us on one of these ! 178: signals in the middle of our check. ! 179: (This code assumes that the command interpreter will not move a process from ! 180: foreground to background without stopping it; if it did we would have ! 181: no way of making the check correctly.) ! 182: .PP ! 183: The routine which handles the signal should clear the catch for the stop ! 184: signal and ! 185: .IR kill (2) ! 186: the processes in its process group with the same signal. The statement ! 187: after this ! 188: .I kill ! 189: will be executed when the process is later continued with SIGCONT. ! 190: .PP ! 191: Thus the code for the catch routine might look like: ! 192: .PP ! 193: .ft B ! 194: .nf ! 195: \&... ! 196: sigset(SIGTSTP, onstop); ! 197: sigset(SIGTTIN, onstop); ! 198: sigset(SIGTTOU, onstop); ! 199: \&... ! 200: ! 201: onstop(signo) ! 202: int signo; ! 203: { ! 204: \fI... restore old terminal state ...\fB ! 205: sigset(signo, SIG_DFL); ! 206: kill(0, signo); ! 207: /* stop here until continued */ ! 208: sigset(signo, onstop); ! 209: \fI... restore our special terminal state ...\fB ! 210: } ! 211: .fi ! 212: .ft R ! 213: .PP ! 214: This routine can also be used to simulate a stop signal. ! 215: .PP ! 216: If a process does not need to save and restore state when it is stopped, ! 217: but wishes to be notified when it is continued after a stop it can catch ! 218: the SIGCONT signal; the SIGCONT handler will be run when the process ! 219: is continued. ! 220: .PP ! 221: Processes which lock data bases such as the password file should ignore ! 222: SIGTTIN, SIGTTOU, and SIGTSTP signals while the data bases are being ! 223: manipulated. While a process is ignoring SIGTTIN signals, reads which ! 224: would normally have hung will return end-of-file; writes which would ! 225: normally have caused SIGTTOU signals are instead permitted while SIGTTOU ! 226: is ignored. ! 227: .PP ! 228: .B "Interrupt-level process handling." ! 229: .PP ! 230: Using the mechanisms of ! 231: .IR sigset (3) ! 232: it is possible to handle process state changes as they occur by providing ! 233: an interrupt-handling routine for the SIGCHLD signal which occurs ! 234: whenever the status of a child process changes. A signal handler for this ! 235: signal is established by: ! 236: .PP ! 237: .RS ! 238: .B "sigset(SIGCHLD, onchild);" ! 239: .RE ! 240: .LP ! 241: The shell or other process would then await a change in child status ! 242: with code of the form: ! 243: .PP ! 244: .nf ! 245: .ft B ! 246: recheck: ! 247: sighold(SIGCHLD); /* start critical section */ ! 248: if (\fIno children to process\fB) { ! 249: sigpause(SIGCHLD); /* release SIGCHLD and pause */ ! 250: goto recheck; ! 251: } ! 252: sigrelse(SIGCHLD); /* end critical region */ ! 253: /* now have a child to process */ ! 254: .fi ! 255: .ft R ! 256: .PP ! 257: Here we are using ! 258: .IR sighold ! 259: to temporarily block the SIGCHLD signal during the checking of the ! 260: data structures telling us whether we have a child to process. ! 261: If we didn't block the signal we would have a race condition since the ! 262: signal might corrupt our decision by arriving shortly after we had ! 263: finished checking the condition but before we paused. ! 264: .PP ! 265: If we need to wait for something to happen, we call ! 266: .I sigpause ! 267: which automically releases the hold on the SIGCHLD signal and waits for a ! 268: signal to occur by starting a ! 269: .IR pause (2). ! 270: Otherwise we simply release the SIGCHLD signal and process the child. ! 271: .I Sigpause ! 272: is similar to the PDP-11 ! 273: .I wait ! 274: instruction, which returns the priority of the processor to the base ! 275: level and idles waiting for an interrupt. ! 276: .PP ! 277: It is important to note that the long-standing bug in the signal mechanism ! 278: which would have lost a SIGCHLD signal which occurred while the signal ! 279: was blocked has been fixed. This is because ! 280: .I sighold ! 281: uses the SIG_HOLD signal set of ! 282: .IR sigsys (2) ! 283: to prevent the signal action from being taken without losing the signal ! 284: if it occurs. Similarly, a signal action set with ! 285: .I sigset ! 286: has the signal held while the action routine is running, ! 287: much as a the interrupt priority of the processor is raised when ! 288: a device interrupt is taken. ! 289: .PP ! 290: In this interrupt driven style of termination processing it is necessary ! 291: that the ! 292: .I wait ! 293: calls used to retrieve status in the SIGCHLD signal handler not block. ! 294: This is because a single invocation of the SIGCHLD handler may indicate ! 295: an arbitrary number of process status changes: signals are not queued. ! 296: This is similar to the case in a disk driver where several drives on ! 297: a single controller may report status at once, while there is only ! 298: one interrupt taken. ! 299: It is even possible for no children to be ready to report status when ! 300: the SIGCHLD handler is invoked, if the signal was posted while the SIGCHLD ! 301: handler was active, and the child was noticed due to a SIGCHLD initially ! 302: sent for another process. ! 303: This causes no problem, since the handler will be called whenever there ! 304: is work to do; the handler just has to collect all information by calling ! 305: .I wait3 ! 306: until it says no more information is available. ! 307: Further status changes are guaranteed to be reflected in another SIGCHLD ! 308: handler call. ! 309: .PP ! 310: .B Restarting system calls. ! 311: .PP ! 312: In older versions of UNIX ! 313: \*(lqslow\*(rq system calls ! 314: were interrupted when signals occurred, ! 315: returning EINTR. ! 316: The new signal mechanism ! 317: .IR sigset (3) ! 318: normally restarts such calls ! 319: rather than interrupting them. ! 320: To summarize: ! 321: .I pause ! 322: and ! 323: .I wait ! 324: return error EINTR (as before), ! 325: .I ioctl ! 326: and ! 327: .I wait3 ! 328: restart, and ! 329: .I read ! 330: and ! 331: .I write ! 332: restart unless some data was read or written in which case they ! 333: return indicating how much data was read or written. ! 334: In programs which use the older ! 335: .IR signal (2) ! 336: mechanisms, ! 337: all of these calls return EINTR ! 338: if a signal occurs during the call. ! 339: .SH SEE ALSO ! 340: csh(1), ioctl(2), killpg(2), setpgrp(2), sigsys(2), wait3(2), signal(3), ! 341: tty(4) ! 342: .SH BUGS ! 343: The job control facilities are not available in standard version 7 UNIX. ! 344: These facilities are still under development and may change in future ! 345: releases of the system as better inter-process communication facilities ! 346: and support for virtual terminals become available. The options and ! 347: specifications of these system calls and even the calls themselves ! 348: are thus subject to change.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.