Home | History | Annotate | Download | only in sem_unlink
      1 /*
      2 * Copyright (c) 2005, Bull S.A..  All rights reserved.
      3 * Created by: Sebastien Decugis
      4 
      5 * This program is free software; you can redistribute it and/or modify it
      6 * under the terms of version 2 of the GNU General Public License as
      7 * published by the Free Software Foundation.
      8 *
      9 * This program is distributed in the hope that it would be useful, but
     10 * WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 *
     13 * You should have received a copy of the GNU General Public License along
     14 * with this program; if not, write the Free Software Foundation, Inc.,
     15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     16 
     17 * This sample test aims to check the following assertion:
     18 *
     19 *  Destruction of the semaphore is postponed until all processes which were using
     20 * the semaphore have called sem_close, _exit or exec.
     21 
     22 * The steps are:
     23 * -> Create a named semaphore with value = 0.
     24 * -> create 3 processes. Each call sem_wait, then sem_post, then sem_close/_exit/exec
     25 * -> the main process unlinks the semaphore, the posts it and close it.
     26 * -> Check all child processes have returned successfully.
     27 
     28 * The test fails if a semaphore operation returns an error in one of the children.
     29 
     30 */
     31 
     32 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
     33 #define _POSIX_C_SOURCE 200112L
     34 
     35 /******************************************************************************/
     36 /*************************** standard includes ********************************/
     37 /******************************************************************************/
     38 #include <pthread.h>
     39 #include <stdarg.h>
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <unistd.h>
     44 
     45 #include <semaphore.h>
     46 #include <errno.h>
     47 #include <fcntl.h>
     48 #include <sys/wait.h>
     49 
     50 /******************************************************************************/
     51 /***************************   Test framework   *******************************/
     52 /******************************************************************************/
     53 #include "../testfrmw/testfrmw.h"
     54 #include "../testfrmw/testfrmw.c"
     55 /* This header is responsible for defining the following macros:
     56  * UNRESOLVED(ret, descr);
     57  *    where descr is a description of the error and ret is an int
     58  *   (error code for example)
     59  * FAILED(descr);
     60  *    where descr is a short text saying why the test has failed.
     61  * PASSED();
     62  *    No parameter.
     63  *
     64  * Both three macros shall terminate the calling process.
     65  * The testcase shall not terminate in any other maneer.
     66  *
     67  * The other file defines the functions
     68  * void output_init()
     69  * void output(char * string, ...)
     70  *
     71  * Those may be used to output information.
     72  */
     73 
     74 /******************************************************************************/
     75 /**************************** Configuration ***********************************/
     76 /******************************************************************************/
     77 #ifndef VERBOSE
     78 #define VERBOSE 1
     79 #endif
     80 
     81 #define SEM_NAME  "/sem_unlink_9_1"
     82 
     83 /******************************************************************************/
     84 /***************************    Test case   ***********************************/
     85 /******************************************************************************/
     86 
     87 /* Operations common to all processes on the semaphore*/
     88 sem_t *common()
     89 {
     90 	int ret;
     91 	sem_t *sem;
     92 
     93 	/* Reconnect to the semaphore */
     94 	sem = sem_open(SEM_NAME, 0);
     95 
     96 	if (sem == SEM_FAILED) {
     97 		UNRESOLVED(errno, "Failed to reconnect the semaphore");
     98 	}
     99 
    100 	/* block until the semaphore is posted */
    101 
    102 	do {
    103 		ret = sem_wait(sem);
    104 	}
    105 	while (ret != 0 && errno == EINTR);
    106 
    107 	if (ret != 0) {
    108 		FAILED("Waiting for the semaphore failed");
    109 	}
    110 
    111 	/* spend some time... */
    112 	sched_yield();
    113 
    114 	sched_yield();
    115 
    116 	sched_yield();
    117 
    118 	/* Post the semaphore back */
    119 	ret = sem_post(sem);
    120 
    121 	if (ret != 0) {
    122 		FAILED("Failed to post the semaphore");
    123 	}
    124 
    125 	return sem;
    126 }
    127 
    128 /* The main test function. */
    129 int main(void)
    130 {
    131 	int ret, status;
    132 	pid_t p1, p2, p3, ctl;
    133 
    134 	sem_t *sem;
    135 
    136 	/* Initialize output */
    137 	output_init();
    138 
    139 	/* Create the semaphore */
    140 	sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 0);
    141 
    142 	if ((sem == SEM_FAILED) && (errno == EEXIST)) {
    143 		sem_unlink(SEM_NAME);
    144 		sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 0);
    145 	}
    146 
    147 	if (sem == SEM_FAILED) {
    148 		UNRESOLVED(errno, "Failed to create the semaphore");
    149 	}
    150 
    151 	/* fork 3 times */
    152 	p1 = fork();
    153 
    154 	if (p1 == -1) {
    155 		UNRESOLVED(errno, "Failed to fork");
    156 	}
    157 
    158 	if (p1 == 0) {		/* child */
    159 		sem = common();
    160 		ret = sem_close(sem);
    161 
    162 		if (ret != 0) {
    163 			FAILED("Failed to sem_close in child");
    164 		}
    165 
    166 		exit(0);
    167 	}
    168 
    169 	p2 = fork();
    170 
    171 	if (p2 == -1) {
    172 		UNRESOLVED(errno, "Failed to fork");
    173 	}
    174 
    175 	if (p2 == 0) {		/* child */
    176 		sem = common();
    177 		_exit(0);
    178 	}
    179 
    180 	p3 = fork();
    181 
    182 	if (p3 == -1) {
    183 		UNRESOLVED(errno, "Failed to fork");
    184 	}
    185 
    186 	if (p3 == 0) {		/* child */
    187 		sem = common();
    188 		ret = execl("/bin/ls", "ls", NULL);
    189 		UNRESOLVED(errno, "Failed to exec");
    190 	}
    191 
    192 	/* Let all processes start and wait for the semaphore */
    193 	sleep(1);
    194 
    195 	/* Unlink */
    196 	ret = sem_unlink(SEM_NAME);
    197 
    198 	if (ret != 0) {
    199 		UNRESOLVED(errno, "Failed to unlink the semaphore");
    200 	}
    201 
    202 	/* Post the semaphore */
    203 	ret = sem_post(sem);
    204 
    205 	if (ret != 0) {
    206 		UNRESOLVED(errno, "Failed to post the semaphore");
    207 	}
    208 
    209 	/* and close it in this process */
    210 	ret = sem_close(sem);
    211 
    212 	if (ret != 0) {
    213 		UNRESOLVED(errno, "Failed to close the semaphore");
    214 	}
    215 
    216 	/* Wait all processes */
    217 	ctl = waitpid(p1, &status, 0);
    218 
    219 	if (ctl != p1) {
    220 		UNRESOLVED(errno, "Waitpid returned the wrong PID");
    221 	}
    222 
    223 	if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
    224 		FAILED("Child 'sem_close' exited abnormally");
    225 	}
    226 
    227 	ctl = waitpid(p2, &status, 0);
    228 
    229 	if (ctl != p2) {
    230 		UNRESOLVED(errno, "Waitpid returned the wrong PID");
    231 	}
    232 
    233 	if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
    234 		FAILED("Child '_exit' exited abnormally");
    235 	}
    236 
    237 	ctl = waitpid(p3, &status, 0);
    238 
    239 	if (ctl != p3) {
    240 		UNRESOLVED(errno, "Waitpid returned the wrong PID");
    241 	}
    242 
    243 	if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
    244 		FAILED("Child 'exec' exited abnormally");
    245 	}
    246 
    247 	/* Test passed */
    248 #if VERBOSE > 0
    249 	output("Test passed\n");
    250 
    251 #endif
    252 	PASSED;
    253 }
    254