113d88268SGregory Neil Shapiro /* 2d0cef73dSGregory Neil Shapiro * Copyright (c) 2000-2001, 2005-2007 Sendmail, Inc. and its suppliers. 313d88268SGregory Neil Shapiro * All rights reserved. 413d88268SGregory Neil Shapiro * 513d88268SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 613d88268SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 713d88268SGregory Neil Shapiro * the sendmail distribution. 813d88268SGregory Neil Shapiro */ 913d88268SGregory Neil Shapiro 1013d88268SGregory Neil Shapiro #include <sm/gen.h> 11d0cef73dSGregory Neil Shapiro SM_RCSID("@(#)$Id: t-sem.c,v 1.16 2007/03/21 23:22:10 ca Exp $") 1213d88268SGregory Neil Shapiro 1313d88268SGregory Neil Shapiro #include <stdio.h> 1413d88268SGregory Neil Shapiro 1513d88268SGregory Neil Shapiro #if SM_CONF_SEM 1613d88268SGregory Neil Shapiro # include <stdlib.h> 1713d88268SGregory Neil Shapiro # include <unistd.h> 1813d88268SGregory Neil Shapiro # include <sysexits.h> 1913d88268SGregory Neil Shapiro # include <sm/heap.h> 2013d88268SGregory Neil Shapiro # include <sm/string.h> 2113d88268SGregory Neil Shapiro # include <sm/signal.h> 2213d88268SGregory Neil Shapiro # include <sm/test.h> 2313d88268SGregory Neil Shapiro # include <sm/sem.h> 2413d88268SGregory Neil Shapiro 25d0cef73dSGregory Neil Shapiro # define T_SM_SEM_KEY (4321L) 26d0cef73dSGregory Neil Shapiro 2713d88268SGregory Neil Shapiro static void 2813d88268SGregory Neil Shapiro delay(t, s) 2913d88268SGregory Neil Shapiro int t; 3013d88268SGregory Neil Shapiro char *s; 3113d88268SGregory Neil Shapiro { 3213d88268SGregory Neil Shapiro if (t > 0) 3313d88268SGregory Neil Shapiro { 3413d88268SGregory Neil Shapiro #if DEBUG 3513d88268SGregory Neil Shapiro fprintf(stderr, "sleep(%d) before %s\n", t, s); 3613d88268SGregory Neil Shapiro #endif /* DEBUG */ 3713d88268SGregory Neil Shapiro sleep(t); 3813d88268SGregory Neil Shapiro } 3913d88268SGregory Neil Shapiro #if DEBUG 4013d88268SGregory Neil Shapiro fprintf(stderr, "%s\n", s); 4113d88268SGregory Neil Shapiro #endif /* DEBUG */ 4213d88268SGregory Neil Shapiro } 4313d88268SGregory Neil Shapiro 4413d88268SGregory Neil Shapiro 4513d88268SGregory Neil Shapiro /* 4613d88268SGregory Neil Shapiro ** SEMINTER -- interactive testing of semaphores. 4713d88268SGregory Neil Shapiro ** 4813d88268SGregory Neil Shapiro ** Parameters: 4913d88268SGregory Neil Shapiro ** owner -- create semaphores. 5013d88268SGregory Neil Shapiro ** 5113d88268SGregory Neil Shapiro ** Returns: 5213d88268SGregory Neil Shapiro ** 0 on success 5313d88268SGregory Neil Shapiro ** < 0 on failure. 5413d88268SGregory Neil Shapiro */ 5513d88268SGregory Neil Shapiro 5613d88268SGregory Neil Shapiro static int 5713d88268SGregory Neil Shapiro seminter(owner) 5813d88268SGregory Neil Shapiro bool owner; 5913d88268SGregory Neil Shapiro { 6013d88268SGregory Neil Shapiro int semid; 6113d88268SGregory Neil Shapiro int t; 6213d88268SGregory Neil Shapiro 63d0cef73dSGregory Neil Shapiro semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner); 6413d88268SGregory Neil Shapiro if (semid < 0) 6513d88268SGregory Neil Shapiro { 6613d88268SGregory Neil Shapiro perror("sm_sem_start failed"); 6713d88268SGregory Neil Shapiro return 1; 6813d88268SGregory Neil Shapiro } 6913d88268SGregory Neil Shapiro 7013d88268SGregory Neil Shapiro while ((t = getchar()) != EOF) 7113d88268SGregory Neil Shapiro { 7213d88268SGregory Neil Shapiro switch (t) 7313d88268SGregory Neil Shapiro { 7413d88268SGregory Neil Shapiro case 'a': 7513d88268SGregory Neil Shapiro delay(0, "try to acq"); 7613d88268SGregory Neil Shapiro if (sm_sem_acq(semid, 0, 2) < 0) 7713d88268SGregory Neil Shapiro { 7813d88268SGregory Neil Shapiro perror("sm_sem_acq failed"); 7913d88268SGregory Neil Shapiro return 1; 8013d88268SGregory Neil Shapiro } 8113d88268SGregory Neil Shapiro delay(0, "acquired"); 8213d88268SGregory Neil Shapiro break; 8313d88268SGregory Neil Shapiro 8413d88268SGregory Neil Shapiro case 'r': 8513d88268SGregory Neil Shapiro delay(0, "try to rel"); 8613d88268SGregory Neil Shapiro if (sm_sem_rel(semid, 0, 2) < 0) 8713d88268SGregory Neil Shapiro { 8813d88268SGregory Neil Shapiro perror("sm_sem_rel failed"); 8913d88268SGregory Neil Shapiro return 1; 9013d88268SGregory Neil Shapiro } 9113d88268SGregory Neil Shapiro delay(0, "released"); 9213d88268SGregory Neil Shapiro break; 9313d88268SGregory Neil Shapiro 9413d88268SGregory Neil Shapiro case 'v': 9513d88268SGregory Neil Shapiro if ((t = sm_sem_get(semid, 0)) < 0) 9613d88268SGregory Neil Shapiro { 9713d88268SGregory Neil Shapiro perror("get_sem failed"); 9813d88268SGregory Neil Shapiro return 1; 9913d88268SGregory Neil Shapiro } 10013d88268SGregory Neil Shapiro printf("semval: %d\n", t); 10113d88268SGregory Neil Shapiro break; 10213d88268SGregory Neil Shapiro 10313d88268SGregory Neil Shapiro } 10413d88268SGregory Neil Shapiro } 10513d88268SGregory Neil Shapiro if (owner) 10613d88268SGregory Neil Shapiro return sm_sem_stop(semid); 10713d88268SGregory Neil Shapiro return 0; 10813d88268SGregory Neil Shapiro } 10913d88268SGregory Neil Shapiro 11013d88268SGregory Neil Shapiro /* 11113d88268SGregory Neil Shapiro ** SEM_CLEANUP -- cleanup if something breaks 11213d88268SGregory Neil Shapiro ** 11313d88268SGregory Neil Shapiro ** Parameters: 11413d88268SGregory Neil Shapiro ** sig -- signal. 11513d88268SGregory Neil Shapiro ** 11613d88268SGregory Neil Shapiro ** Returns: 11713d88268SGregory Neil Shapiro ** none. 11813d88268SGregory Neil Shapiro */ 11913d88268SGregory Neil Shapiro 12013d88268SGregory Neil Shapiro static int semid_c = -1; 12113d88268SGregory Neil Shapiro void 12213d88268SGregory Neil Shapiro sem_cleanup(sig) 12313d88268SGregory Neil Shapiro int sig; 12413d88268SGregory Neil Shapiro { 12513d88268SGregory Neil Shapiro if (semid_c >= 0) 12613d88268SGregory Neil Shapiro (void) sm_sem_stop(semid_c); 12713d88268SGregory Neil Shapiro exit(EX_UNAVAILABLE); 12813d88268SGregory Neil Shapiro } 12913d88268SGregory Neil Shapiro 13013d88268SGregory Neil Shapiro /* 13113d88268SGregory Neil Shapiro ** SEMTEST -- test of semaphores 13213d88268SGregory Neil Shapiro ** 13313d88268SGregory Neil Shapiro ** Parameters: 13413d88268SGregory Neil Shapiro ** owner -- create semaphores. 13513d88268SGregory Neil Shapiro ** 13613d88268SGregory Neil Shapiro ** Returns: 13713d88268SGregory Neil Shapiro ** 0 on success 13813d88268SGregory Neil Shapiro ** < 0 on failure. 13913d88268SGregory Neil Shapiro */ 14013d88268SGregory Neil Shapiro 14113d88268SGregory Neil Shapiro # define MAX_CNT 10 14213d88268SGregory Neil Shapiro 14313d88268SGregory Neil Shapiro static int 14413d88268SGregory Neil Shapiro semtest(owner) 14513d88268SGregory Neil Shapiro int owner; 14613d88268SGregory Neil Shapiro { 14713d88268SGregory Neil Shapiro int semid, r; 14813d88268SGregory Neil Shapiro int cnt = 0; 14913d88268SGregory Neil Shapiro 150d0cef73dSGregory Neil Shapiro semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner); 15113d88268SGregory Neil Shapiro if (semid < 0) 15213d88268SGregory Neil Shapiro { 15313d88268SGregory Neil Shapiro perror("sm_sem_start failed"); 15413d88268SGregory Neil Shapiro return -1; 15513d88268SGregory Neil Shapiro } 15613d88268SGregory Neil Shapiro 15713d88268SGregory Neil Shapiro if (owner) 15813d88268SGregory Neil Shapiro { 15913d88268SGregory Neil Shapiro /* just in case someone kills the program... */ 16013d88268SGregory Neil Shapiro semid_c = semid; 16113d88268SGregory Neil Shapiro (void) sm_signal(SIGHUP, sem_cleanup); 16213d88268SGregory Neil Shapiro (void) sm_signal(SIGINT, sem_cleanup); 16313d88268SGregory Neil Shapiro (void) sm_signal(SIGTERM, sem_cleanup); 16413d88268SGregory Neil Shapiro 16513d88268SGregory Neil Shapiro delay(1, "parent: acquire 1"); 16613d88268SGregory Neil Shapiro cnt = 0; 16713d88268SGregory Neil Shapiro do 16813d88268SGregory Neil Shapiro { 16913d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0); 17013d88268SGregory Neil Shapiro if (r < 0) 17113d88268SGregory Neil Shapiro { 17213d88268SGregory Neil Shapiro sleep(1); 17313d88268SGregory Neil Shapiro ++cnt; 17413d88268SGregory Neil Shapiro } 17513d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 17613d88268SGregory Neil Shapiro SM_TEST(r >= 0); 17713d88268SGregory Neil Shapiro if (r < 0) 17813d88268SGregory Neil Shapiro return r; 17913d88268SGregory Neil Shapiro 18013d88268SGregory Neil Shapiro delay(3, "parent: release 1"); 18113d88268SGregory Neil Shapiro cnt = 0; 18213d88268SGregory Neil Shapiro do 18313d88268SGregory Neil Shapiro { 18413d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0); 18513d88268SGregory Neil Shapiro if (r < 0) 18613d88268SGregory Neil Shapiro { 18713d88268SGregory Neil Shapiro sleep(1); 18813d88268SGregory Neil Shapiro ++cnt; 18913d88268SGregory Neil Shapiro } 19013d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 19113d88268SGregory Neil Shapiro SM_TEST(r >= 0); 19213d88268SGregory Neil Shapiro if (r < 0) 19313d88268SGregory Neil Shapiro return r; 19413d88268SGregory Neil Shapiro 19513d88268SGregory Neil Shapiro delay(1, "parent: getval"); 19613d88268SGregory Neil Shapiro cnt = 0; 19713d88268SGregory Neil Shapiro do 19813d88268SGregory Neil Shapiro { 19913d88268SGregory Neil Shapiro r = sm_sem_get(semid, 0); 20013d88268SGregory Neil Shapiro if (r <= 0) 20113d88268SGregory Neil Shapiro { 20213d88268SGregory Neil Shapiro sleep(1); 20313d88268SGregory Neil Shapiro ++cnt; 20413d88268SGregory Neil Shapiro } 20513d88268SGregory Neil Shapiro } while (r <= 0 && cnt <= MAX_CNT); 20613d88268SGregory Neil Shapiro SM_TEST(r > 0); 20713d88268SGregory Neil Shapiro if (r <= 0) 20813d88268SGregory Neil Shapiro return r; 20913d88268SGregory Neil Shapiro 21013d88268SGregory Neil Shapiro delay(1, "parent: acquire 2"); 21113d88268SGregory Neil Shapiro cnt = 0; 21213d88268SGregory Neil Shapiro do 21313d88268SGregory Neil Shapiro { 21413d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0); 21513d88268SGregory Neil Shapiro if (r < 0) 21613d88268SGregory Neil Shapiro { 21713d88268SGregory Neil Shapiro sleep(1); 21813d88268SGregory Neil Shapiro ++cnt; 21913d88268SGregory Neil Shapiro } 22013d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 22113d88268SGregory Neil Shapiro SM_TEST(r >= 0); 22213d88268SGregory Neil Shapiro if (r < 0) 22313d88268SGregory Neil Shapiro return r; 22413d88268SGregory Neil Shapiro 22513d88268SGregory Neil Shapiro cnt = 0; 22613d88268SGregory Neil Shapiro do 22713d88268SGregory Neil Shapiro { 22813d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0); 22913d88268SGregory Neil Shapiro if (r < 0) 23013d88268SGregory Neil Shapiro { 23113d88268SGregory Neil Shapiro sleep(1); 23213d88268SGregory Neil Shapiro ++cnt; 23313d88268SGregory Neil Shapiro } 23413d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 23513d88268SGregory Neil Shapiro SM_TEST(r >= 0); 23613d88268SGregory Neil Shapiro if (r < 0) 23713d88268SGregory Neil Shapiro return r; 23813d88268SGregory Neil Shapiro } 23913d88268SGregory Neil Shapiro else 24013d88268SGregory Neil Shapiro { 24113d88268SGregory Neil Shapiro delay(1, "child: acquire 1"); 24213d88268SGregory Neil Shapiro cnt = 0; 24313d88268SGregory Neil Shapiro do 24413d88268SGregory Neil Shapiro { 24513d88268SGregory Neil Shapiro r = sm_sem_acq(semid, 0, 0); 24613d88268SGregory Neil Shapiro if (r < 0) 24713d88268SGregory Neil Shapiro { 24813d88268SGregory Neil Shapiro sleep(1); 24913d88268SGregory Neil Shapiro ++cnt; 25013d88268SGregory Neil Shapiro } 25113d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 25213d88268SGregory Neil Shapiro SM_TEST(r >= 0); 25313d88268SGregory Neil Shapiro if (r < 0) 25413d88268SGregory Neil Shapiro return r; 25513d88268SGregory Neil Shapiro 25613d88268SGregory Neil Shapiro delay(1, "child: release 1"); 25713d88268SGregory Neil Shapiro cnt = 0; 25813d88268SGregory Neil Shapiro do 25913d88268SGregory Neil Shapiro { 26013d88268SGregory Neil Shapiro r = sm_sem_rel(semid, 0, 0); 26113d88268SGregory Neil Shapiro if (r < 0) 26213d88268SGregory Neil Shapiro { 26313d88268SGregory Neil Shapiro sleep(1); 26413d88268SGregory Neil Shapiro ++cnt; 26513d88268SGregory Neil Shapiro } 26613d88268SGregory Neil Shapiro } while (r < 0 && cnt <= MAX_CNT); 26713d88268SGregory Neil Shapiro SM_TEST(r >= 0); 26813d88268SGregory Neil Shapiro if (r < 0) 26913d88268SGregory Neil Shapiro return r; 27013d88268SGregory Neil Shapiro 27113d88268SGregory Neil Shapiro } 27213d88268SGregory Neil Shapiro if (owner) 27313d88268SGregory Neil Shapiro return sm_sem_stop(semid); 27413d88268SGregory Neil Shapiro return 0; 27513d88268SGregory Neil Shapiro } 27613d88268SGregory Neil Shapiro 27713d88268SGregory Neil Shapiro int 27813d88268SGregory Neil Shapiro main(argc, argv) 27913d88268SGregory Neil Shapiro int argc; 28013d88268SGregory Neil Shapiro char *argv[]; 28113d88268SGregory Neil Shapiro { 28213d88268SGregory Neil Shapiro bool interactive = false; 28313d88268SGregory Neil Shapiro bool owner = false; 28413d88268SGregory Neil Shapiro int ch; 28513d88268SGregory Neil Shapiro int r = 0; 28613d88268SGregory Neil Shapiro 28713d88268SGregory Neil Shapiro # define OPTIONS "io" 28813d88268SGregory Neil Shapiro while ((ch = getopt(argc, argv, OPTIONS)) != -1) 28913d88268SGregory Neil Shapiro { 29013d88268SGregory Neil Shapiro switch ((char) ch) 29113d88268SGregory Neil Shapiro { 29213d88268SGregory Neil Shapiro case 'i': 29313d88268SGregory Neil Shapiro interactive = true; 29413d88268SGregory Neil Shapiro break; 29513d88268SGregory Neil Shapiro 29613d88268SGregory Neil Shapiro case 'o': 29713d88268SGregory Neil Shapiro owner = true; 29813d88268SGregory Neil Shapiro break; 29913d88268SGregory Neil Shapiro 30013d88268SGregory Neil Shapiro default: 30113d88268SGregory Neil Shapiro break; 30213d88268SGregory Neil Shapiro } 30313d88268SGregory Neil Shapiro } 30413d88268SGregory Neil Shapiro 30513d88268SGregory Neil Shapiro if (interactive) 30613d88268SGregory Neil Shapiro r = seminter(owner); 30713d88268SGregory Neil Shapiro else 30813d88268SGregory Neil Shapiro { 30913d88268SGregory Neil Shapiro pid_t pid; 31013d88268SGregory Neil Shapiro 31113d88268SGregory Neil Shapiro printf("This test takes about 8 seconds.\n"); 3124e4196cbSGregory Neil Shapiro printf("If it takes longer than 30 seconds, please interrupt it\n"); 31313d88268SGregory Neil Shapiro printf("and compile again without semaphore support, i.e.,"); 31413d88268SGregory Neil Shapiro printf("-DSM_CONF_SEM=0\n"); 31513d88268SGregory Neil Shapiro if ((pid = fork()) < 0) 31613d88268SGregory Neil Shapiro { 31713d88268SGregory Neil Shapiro perror("fork failed\n"); 31813d88268SGregory Neil Shapiro return -1; 31913d88268SGregory Neil Shapiro } 32013d88268SGregory Neil Shapiro 32113d88268SGregory Neil Shapiro sm_test_begin(argc, argv, "test semaphores"); 32213d88268SGregory Neil Shapiro if (pid == 0) 32313d88268SGregory Neil Shapiro { 32413d88268SGregory Neil Shapiro /* give the parent the chance to setup data */ 32513d88268SGregory Neil Shapiro sleep(1); 32613d88268SGregory Neil Shapiro r = semtest(false); 32713d88268SGregory Neil Shapiro } 32813d88268SGregory Neil Shapiro else 32913d88268SGregory Neil Shapiro { 33013d88268SGregory Neil Shapiro r = semtest(true); 33113d88268SGregory Neil Shapiro } 33213d88268SGregory Neil Shapiro SM_TEST(r == 0); 33313d88268SGregory Neil Shapiro return sm_test_end(); 33413d88268SGregory Neil Shapiro } 33513d88268SGregory Neil Shapiro return r; 33613d88268SGregory Neil Shapiro } 33713d88268SGregory Neil Shapiro #else /* SM_CONF_SEM */ 33813d88268SGregory Neil Shapiro int 33913d88268SGregory Neil Shapiro main(argc, argv) 34013d88268SGregory Neil Shapiro int argc; 34113d88268SGregory Neil Shapiro char *argv[]; 34213d88268SGregory Neil Shapiro { 34313d88268SGregory Neil Shapiro printf("No support for semaphores configured on this machine\n"); 34413d88268SGregory Neil Shapiro return 0; 34513d88268SGregory Neil Shapiro } 34613d88268SGregory Neil Shapiro #endif /* SM_CONF_SEM */ 347