xref: /freebsd/contrib/sendmail/libsm/t-sem.c (revision d0cef73d40a409e3116f095b83633b1364e95741)
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