00001 /* 00002 Unified Event Manager test program 00003 AUP2, Sec. 5.18.2 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 #include "uem.h" 00023 #include <sys/msg.h> 00024 #include <sys/sem.h> 00025 #ifdef POSIX_IPC 00026 #include <mqueue.h> 00027 #include <semaphore.h> 00028 #endif 00029 00030 #define SYSTEMV_MSG_NAME "/tmp/uemtst_systemv_msg" 00031 #define POSIX_MSG_NAME "/uemtst_posix_msg" 00032 #define POSIX_SEM_NAME "/uemtst_posix_sem" 00033 #define MSG_SIZE 100 00034 #define TEST_SIGNAL SIGHUP 00035 00036 static void handler_nothing(int signum) 00037 { 00038 printf("Got %d in handler\n", signum); 00039 } 00040 00041 static bool setup_signal(void) 00042 { 00043 pid_t pid; 00044 00045 if ((pid = fork()) == 0) { 00046 int i; 00047 00048 srand(getpid()); 00049 for (i = 0; i < 10; i++) { 00050 sleep(rand() % 9 + 1); 00051 ec_neg1( kill(getppid(), TEST_SIGNAL) ) 00052 } 00053 exit(EXIT_SUCCESS); 00054 } 00055 ec_false( uem_register_signal(TEST_SIGNAL, NULL) ) 00056 return true; 00057 00058 EC_CLEANUP_BGN 00059 if (pid == 0) 00060 exit(EXIT_FAILURE); 00061 else 00062 return false; 00063 EC_CLEANUP_END 00064 } 00065 00066 static bool setup_systemv_sem(void) 00067 { 00068 int semid; 00069 key_t key; 00070 pid_t pid; 00071 struct sembuf sop; 00072 00073 ec_neg1( key = ftok(SYSTEMV_MSG_NAME, 2) ) 00074 if ((semid = semget(key, 1, PERM_FILE)) != -1) 00075 (void)semctl(semid, 0, IPC_RMID, NULL); 00076 ec_neg1( semid = semget(key, 1, IPC_CREAT | PERM_FILE) ) 00077 if ((pid = fork()) == 0) { 00078 int i; 00079 00080 sop.sem_num = 0; 00081 sop.sem_op = 1; 00082 sop.sem_flg = 0; 00083 srand(getpid()); 00084 for (i = 0; i < 10; i++) { 00085 sleep(rand() % 9 + 1); 00086 ec_neg1( semop(semid, &sop, 1) ) 00087 } 00088 exit(EXIT_SUCCESS); 00089 } 00090 sop.sem_num = 0; 00091 sop.sem_op = -1; 00092 sop.sem_flg = 0; 00093 ec_false( uem_register_svsem(semid, &sop, 1, NULL) ) 00094 return true; 00095 00096 EC_CLEANUP_BGN 00097 if (pid == 0) 00098 exit(EXIT_FAILURE); 00099 else 00100 return false; 00101 EC_CLEANUP_END 00102 } 00103 00104 static bool setup_systemv_msg(void) 00105 { 00106 int mqid; 00107 key_t key; 00108 pid_t pid; 00109 00110 ec_neg1( key = ftok(SYSTEMV_MSG_NAME, 1) ) 00111 if ((mqid = msgget(key, PERM_FILE)) != -1) 00112 (void)msgctl(mqid, IPC_RMID, NULL); 00113 ec_neg1( mqid = msgget(key, IPC_CREAT | PERM_FILE) ) 00114 if ((pid = fork()) == 0) { 00115 int i; 00116 struct { 00117 long mtype; 00118 char mtext[MSG_SIZE - sizeof(long)]; 00119 } msg; 00120 00121 msg.mtype = 1; 00122 srand(getpid()); 00123 for (i = 0; i < 10; i++) { 00124 sleep(rand() % 9 + 1); 00125 snprintf(msg.mtext, sizeof(msg.mtext), "System V msg #%d", i); 00126 ec_neg1( msgsnd(mqid, &msg, sizeof(msg.mtext), 0) ) 00127 } 00128 exit(EXIT_SUCCESS); 00129 } 00130 ec_false( uem_register_svmsg(mqid, MSG_SIZE, NULL) ) 00131 return true; 00132 00133 EC_CLEANUP_BGN 00134 if (pid == 0) 00135 exit(EXIT_FAILURE); 00136 else 00137 return false; 00138 EC_CLEANUP_END 00139 } 00140 00141 static bool setup_posix_sem(void) 00142 { 00143 #ifdef POSIX_IPC 00144 sem_t *sem; 00145 pid_t pid; 00146 00147 if ((sem = sem_open(POSIX_SEM_NAME, O_RDWR | O_CREAT, 00148 PERM_FILE, NULL)) == SEM_FAILED) /* note strange error return */ 00149 EC_FAIL 00150 if ((pid = fork()) == 0) { 00151 int i; 00152 00153 srand(getpid()); 00154 for (i = 0; i < 10; i++) { 00155 sleep(rand() % 9 + 1); 00156 ec_neg1( sem_post(sem) ) 00157 } 00158 exit(EXIT_SUCCESS); 00159 } 00160 ec_false( uem_register_pxsem(sem, NULL) ) 00161 return true; 00162 00163 EC_CLEANUP_BGN 00164 if (pid == 0) 00165 exit(EXIT_FAILURE); 00166 else 00167 return false; 00168 EC_CLEANUP_END 00169 #else 00170 return true; 00171 #endif 00172 } 00173 00174 static bool setup_posix_msg(void) 00175 { 00176 #ifdef POSIX_IPC 00177 mqd_t mqd; 00178 pid_t pid; 00179 00180 ec_neg1( mqd = mq_open(POSIX_MSG_NAME, O_RDWR | O_CREAT, 00181 PERM_FILE, NULL) ) 00182 if ((pid = fork()) == 0) { 00183 int i; 00184 char msg[MSG_SIZE]; 00185 00186 srand(getpid()); 00187 for (i = 0; i < 10; i++) { 00188 sleep(rand() % 9 + 1); 00189 snprintf(msg, sizeof(msg), "POSIX msg #%d", i); 00190 ec_neg1( mq_send(mqd, msg, MSG_SIZE, 0) ) 00191 } 00192 exit(EXIT_SUCCESS); 00193 } 00194 ec_false( uem_register_pxmsg(mqd, NULL) ) 00195 return true; 00196 00197 EC_CLEANUP_BGN 00198 if (pid == 0) 00199 exit(EXIT_FAILURE); 00200 else 00201 return false; 00202 EC_CLEANUP_END 00203 #else 00204 return true; 00205 #endif 00206 } 00207 00208 static bool setup_process(void) 00209 { 00210 pid_t pid; 00211 00212 if ((pid = fork()) == 0) { 00213 sleep(3); 00214 exit(1234); 00215 } 00216 ec_false( uem_register_process(pid, NULL) ) 00217 return true; 00218 00219 EC_CLEANUP_BGN 00220 if (pid == 0) 00221 exit(EXIT_FAILURE); 00222 else 00223 return false; 00224 EC_CLEANUP_END 00225 } 00226 00227 static bool setup_fdset(void) 00228 { 00229 pid_t pid; 00230 int pfd1[2], pfd2[2]; 00231 fd_set fdset; 00232 00233 ec_neg1( signal(SIGPIPE, SIG_IGN) ) 00234 ec_neg1( pipe(pfd1) ) 00235 ec_neg1( pipe(pfd2) ) 00236 if ((pid = fork()) == 0) { 00237 int i; 00238 00239 srand(getpid()); 00240 ec_neg1( close(pfd1[0]) ) 00241 ec_neg1( close(pfd2[1]) ) 00242 for (i = 0; i < 10; i++) { 00243 int x; 00244 00245 sleep(rand() % 9 + 1); 00246 ec_neg1( write(pfd1[1], &i, sizeof(i)) ) 00247 ec_neg1( read(pfd2[0], &x, sizeof(x)) ) 00248 } 00249 ec_neg1( close(pfd1[1]) ) 00250 ec_neg1( close(pfd2[0]) ) 00251 exit(EXIT_SUCCESS); 00252 } 00253 ec_neg1( close(pfd1[1]) ) 00254 ec_neg1( close(pfd2[0]) ) 00255 while (true) { 00256 setblock(pfd2[1], false); 00257 if (write(pfd2[1], "abcde", 5) == -1) { 00258 if (errno == EAGAIN) 00259 break; 00260 else 00261 EC_FAIL 00262 } 00263 } 00264 FD_ZERO(&fdset); 00265 FD_SET(pfd1[0], &fdset); 00266 ec_false( uem_register_fdset(pfd1[0] + 1, &fdset, UEM_FD_READ, NULL) ) 00267 FD_ZERO(&fdset); 00268 FD_SET(pfd2[1], &fdset); 00269 ec_false( uem_register_fdset(pfd2[1] + 1, &fdset, UEM_FD_WRITE, NULL) ) 00270 return true; 00271 00272 EC_CLEANUP_BGN 00273 if (pid == 0) 00274 exit(EXIT_FAILURE); 00275 else 00276 return false; 00277 EC_CLEANUP_END 00278 } 00279 00280 int main(void) 00281 { 00282 struct uem_event *e; 00283 00284 (void)close(open(SYSTEMV_MSG_NAME, O_WRONLY | O_CREAT, 0)); 00285 ec_false( uem_bgn() ) 00286 ec_false( setup_systemv_msg() ) 00287 ec_false( setup_systemv_sem() ) 00288 ec_false( setup_posix_msg() ) 00289 ec_false( setup_posix_sem() ) 00290 ec_false( setup_signal() ) 00291 ec_false( setup_process() ) 00292 ec_false( setup_fdset() ) 00293 ec_false( uem_register_heartbeat(3 * 1000000, NULL) ) 00294 while (true) { 00295 ec_null( e = uem_wait() ) 00296 if (e->ue_errno != 0) 00297 printf("***** EVENT ERROR: (type = %d) -- %s\n", 00298 e->ue_reg->ur_type, strerror(e->ue_errno)); 00299 else 00300 switch (e->ue_reg->ur_type) { 00301 case UEM_SVMSG: 00302 { 00303 struct msg { 00304 long mtype; 00305 char mtext[1]; 00306 }; 00307 printf("Got SysV message: %s\n", 00308 ((struct msg *)e->ue_buf)->mtext); 00309 } 00310 break; 00311 case UEM_PXMSG: 00312 printf("Got POSIX message: %s\n", (char *)e->ue_buf); 00313 break; 00314 case UEM_SVSEM: 00315 printf("Got SysV semaphore\n"); 00316 break; 00317 case UEM_PXSEM: 00318 printf("Got POSIX semaphore\n"); 00319 break; 00320 case UEM_FD_READ: 00321 { 00322 int n; 00323 ssize_t nread; 00324 00325 ec_neg1( nread = read(e->ue_result, &n, sizeof(n)) ) 00326 if (nread == 0) { 00327 ec_neg1( close(e->ue_result) ) 00328 ec_false( uem_unregister(e) ) 00329 } 00330 else 00331 printf("Got fd -- read %d\n", n); 00332 } 00333 break; 00334 case UEM_FD_WRITE: 00335 { 00336 if (write(e->ue_result, "a", 1) == -1) { 00337 if (errno == EPIPE) { 00338 printf("EPIPE on pipe... unregistering\n"); 00339 ec_neg1( close(e->ue_result) ) 00340 ec_false( uem_unregister(e) ) 00341 } 00342 else 00343 EC_FAIL 00344 } 00345 else 00346 printf("Got fd -- write\n"); 00347 } 00348 break; 00349 case UEM_FD_ERROR: 00350 break; 00351 case UEM_SIG: 00352 printf("Got signal: %d\n", (int)e->ue_result); 00353 break; 00354 case UEM_PROCESS: 00355 printf("Got process status: %ld\n", (long)e->ue_result); 00356 break; 00357 case UEM_HEARTBEAT: 00358 printf("Got heartbeat\n"); 00359 break; 00360 case UEM_NONE: 00361 default: 00362 printf("Strange event type: %d\n", e->ue_reg->ur_type); 00363 break; 00364 } 00365 uem_free(e); 00366 } 00367 ec_false( uem_end() ) 00368 exit(EXIT_SUCCESS); 00369 00370 EC_CLEANUP_BGN 00371 exit(EXIT_FAILURE); 00372 EC_CLEANUP_END 00373 }