00001 /* 00002 Process-synchronization examples 00003 AUP2, Sec. 9.02.3 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 /*[try1]*/ 00023 void try1(void) 00024 { 00025 if (fork() == 0) { 00026 printf("child\n"); 00027 exit(EXIT_SUCCESS); 00028 } 00029 printf("parent\n"); 00030 return; 00031 } 00032 /*[]*/ 00033 // SIGUSR1 arriving before handler is installed will kill process 00034 /*[try2]*/ 00035 static volatile sig_atomic_t got_sig; 00036 00037 static void handler(int signum) 00038 { 00039 if (signum == SIGUSR1) 00040 got_sig = 1; 00041 } 00042 00043 void try2(void) 00044 { 00045 pid_t pid; 00046 00047 got_sig = 0; 00048 ec_neg1( pid = fork() ) 00049 if (pid == 0) { 00050 struct sigaction act; 00051 00052 memset(&act, 0, sizeof(act)); 00053 act.sa_handler = handler; 00054 ec_neg1( sigaction(SIGUSR1, &act, NULL) ) 00055 while (got_sig == 0) 00056 if (pause() == -1 && errno != EINTR) 00057 EC_FAIL 00058 printf("child\n"); 00059 exit(EXIT_SUCCESS); 00060 } 00061 printf("parent\n"); 00062 ec_neg1( kill(pid, SIGUSR1) ) 00063 return; 00064 00065 EC_CLEANUP_BGN 00066 EC_FLUSH("try2") 00067 EC_CLEANUP_END 00068 } 00069 /*[]*/ 00070 // fixed: SIGUSR1 arriving before handler is installed will kill process 00071 // arriving between while and pause will cause it to be lost 00072 /*[try3]*/ 00073 void try3(void) 00074 { 00075 sigset_t set; 00076 pid_t pid; 00077 00078 got_sig = 0; 00079 ec_neg1( sigemptyset(&set) ) 00080 ec_neg1( sigaddset(&set, SIGUSR1) ) 00081 ec_neg1( sigprocmask(SIG_SETMASK, &set, NULL) ) 00082 ec_neg1( pid = fork() ) 00083 if (pid == 0) { 00084 struct sigaction act; 00085 sigset_t suspendset; 00086 00087 memset(&act, 0, sizeof(act)); 00088 act.sa_handler = handler; 00089 ec_neg1( sigaction(SIGUSR1, &act, NULL) ) 00090 ec_neg1( sigfillset(&suspendset) ) 00091 ec_neg1( sigdelset(&suspendset, SIGUSR1) ) 00092 ec_neg1( sigprocmask(SIG_SETMASK, &suspendset, NULL) ) 00093 while (got_sig == 0) 00094 if (pause() == -1 && errno != EINTR) 00095 EC_FAIL 00096 printf("child\n"); 00097 exit(EXIT_SUCCESS); 00098 } 00099 printf("parent\n"); 00100 ec_neg1( kill(pid, SIGUSR1) ) 00101 return; 00102 00103 EC_CLEANUP_BGN 00104 EC_FLUSH("try3") 00105 EC_CLEANUP_END 00106 } 00107 /*[try4]*/ 00108 void try4(void) 00109 { 00110 sigset_t set; 00111 pid_t pid; 00112 00113 got_sig = 0; 00114 ec_neg1( sigemptyset(&set) ) 00115 ec_neg1( sigaddset(&set, SIGUSR1) ) 00116 ec_neg1( sigprocmask(SIG_SETMASK, &set, NULL) ) 00117 ec_neg1( pid = fork() ) 00118 if (pid == 0) { 00119 struct sigaction act; 00120 sigset_t suspendset; 00121 00122 memset(&act, 0, sizeof(act)); 00123 act.sa_handler = handler; 00124 ec_neg1( sigaction(SIGUSR1, &act, NULL) ) 00125 ec_neg1( sigfillset(&suspendset) ) 00126 ec_neg1( sigdelset(&suspendset, SIGUSR1) ) 00127 if (sigsuspend(&suspendset) == -1 && errno != EINTR) 00128 EC_FAIL 00129 printf("child\n"); 00130 exit(EXIT_SUCCESS); 00131 } 00132 printf("parent\n"); 00133 ec_neg1( kill(pid, SIGUSR1) ) 00134 return; 00135 00136 EC_CLEANUP_BGN 00137 EC_FLUSH("try4") 00138 EC_CLEANUP_END 00139 } 00140 00141 /* 00142 FreeBSD defines sigwait only if the pthread libraries are included, 00143 but then sigaction seems to fail with EINVAL. If you manage to sort 00144 this out, please send email to aup#basepath.com. 00145 */ 00146 #ifndef FREEBSD 00147 /*[try5]*/ 00148 void try5(void) 00149 { 00150 sigset_t set; 00151 pid_t pid; 00152 00153 ec_neg1( sigemptyset(&set) ) 00154 ec_neg1( sigaddset(&set, SIGUSR1) ) 00155 ec_neg1( sigprocmask(SIG_SETMASK, &set, NULL) ) 00156 ec_neg1( pid = fork() ) 00157 if (pid == 0) { 00158 int signum; 00159 00160 ec_rv( sigwait(&set, &signum) ) 00161 printf("child\n"); 00162 exit(EXIT_SUCCESS); 00163 } 00164 printf("parent\n"); 00165 ec_neg1( kill(pid, SIGUSR1) ) 00166 return; 00167 00168 EC_CLEANUP_BGN 00169 EC_FLUSH("try5") 00170 EC_CLEANUP_END 00171 } 00172 /*[]*/ 00173 #endif /* FREEBSD */ 00174 /* 00175 Same thing, but with a pipe. 00176 */ 00177 /*[try6]*/ 00178 void try6(void) 00179 { 00180 int pfd[2]; 00181 pid_t pid; 00182 00183 ec_neg1( pipe(pfd) ) 00184 ec_neg1( pid = fork() ) 00185 if (pid == 0) { 00186 char c; 00187 00188 ec_neg1( close(pfd[1]) ) 00189 ec_neg1( read(pfd[0], &c, 1) ) 00190 ec_neg1( close(pfd[0]) ) 00191 printf("child\n"); 00192 exit(EXIT_SUCCESS); 00193 } 00194 printf("parent\n"); 00195 ec_neg1( close(pfd[0]) ) 00196 ec_neg1( close(pfd[1]) ) 00197 return; 00198 00199 EC_CLEANUP_BGN 00200 EC_FLUSH("try6") 00201 EC_CLEANUP_END 00202 } 00203 /*[]*/ 00204 int main(void) 00205 { 00206 try1(); 00207 sleep(2); 00208 try2(); 00209 sleep(2); 00210 try3(); 00211 sleep(2); 00212 try4(); 00213 sleep(2); 00214 #ifndef FREEBSD 00215 try5(); 00216 sleep(2); 00217 #endif /* FREEBSD */ 00218 try6(); 00219 sleep(2); 00220 exit(EXIT_SUCCESS); 00221 }