1/*
2* Copyright (c) 2004, 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., 59
15* Temple Place - Suite 330, Boston MA 02111-1307, USA.
16
17
18* This sample test aims to check the following assertion:
19*
20* The file locks are not inherited by the child process.
21
22* The steps are:
23* -> lock stdout
24* -> fork
25* -> child creates a thread
26* -> child thread trylock stdout
27* -> join the child
28
29* The test fails if the child thread cannot lock the file
30* -- this would mean the child process got stdout file lock ownership.
31
32*/
33
34
35/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
36#define _POSIX_C_SOURCE 200112L
37
38/********************************************************************************************/
39/****************************** standard includes *****************************************/
40/********************************************************************************************/
41#include <pthread.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48#include <sys/wait.h>
49 #include <errno.h>
50
51
52/********************************************************************************************/
53/******************************   Test framework   *****************************************/
54/********************************************************************************************/
55#include "testfrmw.h"
56 #include "testfrmw.c"
57/* This header is responsible for defining the following macros:
58 * UNRESOLVED(ret, descr);
59 *    where descr is a description of the error and ret is an int (error code for example)
60 * FAILED(descr);
61 *    where descr is a short text saying why the test has failed.
62 * PASSED();
63 *    No parameter.
64 *
65 * Both three macros shall terminate the calling process.
66 * The testcase shall not terminate in any other maneer.
67 *
68 * The other file defines the functions
69 * void output_init()
70 * void output(char * string, ...)
71 *
72 * Those may be used to output information.
73 */
74
75/********************************************************************************************/
76/********************************** Configuration ******************************************/
77/********************************************************************************************/
78#ifndef VERBOSE
79#define VERBOSE 1
80#endif
81
82/********************************************************************************************/
83/***********************************    Test case   *****************************************/
84/********************************************************************************************/
85/* Thread function */
86void * threaded( void * arg )
87{
88	int ret;
89	ret = ftrylockfile( stdout );
90
91	if ( ret != 0 )
92	{
93		FAILED( "The child process is owning the file lock." );
94	}
95
96#if VERBOSE > 1
97
98	output( "The file lock was not inherited in the child process\n" );
99
100#endif
101
102	return NULL;
103}
104
105/* The main test function. */
106int main( int argc, char * argv[] )
107{
108	int ret, status;
109	pid_t child, ctl;
110	pthread_t ch;
111
112	/* Initialize output */
113	output_init();
114
115	/* lock the stdout file */
116	flockfile( stdout );
117
118	/* Create the child */
119	child = fork();
120
121	if ( child == ( pid_t ) - 1 )
122	{
123		UNRESOLVED( errno, "Failed to fork" );
124	}
125
126	/* child */
127	if ( child == ( pid_t ) 0 )
128	{
129
130		ret = pthread_create( &ch, NULL, threaded, NULL );
131
132		if ( ret != 0 )
133		{
134			UNRESOLVED( ret, "Failed to create a thread" );
135		}
136
137		ret = pthread_join( ch, NULL );
138
139		if ( ret != 0 )
140		{
141			UNRESOLVED( ret, "Failed to join the thread" );
142		}
143
144		/* We're done */
145		exit( PTS_PASS );
146	}
147
148	/* Parent sleeps for a while to create contension in case the file lock is inherited */
149	sleep( 1 );
150
151	funlockfile( stdout );
152
153	/* Parent joins the child */
154	ctl = waitpid( child, &status, 0 );
155
156	if ( ctl != child )
157	{
158		UNRESOLVED( errno, "Waitpid returned the wrong PID" );
159	}
160
161	if ( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != PTS_PASS ) )
162	{
163		FAILED( "Child exited abnormally" );
164	}
165
166	/* Test passed */
167#if VERBOSE > 0
168
169	output( "Test passed\n" );
170
171#endif
172
173	PASSED;
174}
175
176
177