Merge pull request #2301 from sonndinh/remove-dup-reactor-functions
[ACE_TAO.git] / ACE / tests / Process_Mutex_Test.cpp
blobcc522300d5465b47881388a6babb534255be5de8
1 //=============================================================================
2 /**
3 * @file Process_Mutex_Test.cpp
5 * Tests an <ACE_Process_Mutex> shared between multiple child processes.
7 * @author Irfan Pyarali <irfan@cs.wustl.edu>
8 */
9 //=============================================================================
11 #include "test_config.h"
12 #include "ace/Mutex.h"
13 #include "ace/Process.h"
14 #include "ace/Process_Mutex.h"
15 #include "ace/Get_Opt.h"
16 #include "ace/ACE.h"
17 #include "ace/OS_NS_stdio.h"
18 #include "ace/OS_NS_string.h"
19 #include "ace/OS_NS_fcntl.h"
20 #include "ace/os_include/os_dirent.h"
22 static int release_mutex = 1;
23 static int child_process = 0;
24 static const ACE_TCHAR *mutex_name = ACE_DEFAULT_MUTEX;
25 #if defined (__Lynx__)
26 static const u_int n_processes = 4;
27 #else /* ! __Lynx__ */
28 static const u_int n_processes = ACE_MAX_PROCESSES;
29 #endif /* ! __Lynx__ */
31 // Explain usage and exit.
32 static void
33 print_usage_and_die ()
35 ACE_DEBUG ((LM_DEBUG,
36 ACE_TEXT ("usage: %n [-d (don't release mutex)] ")
37 ACE_TEXT ("[-c (child process)] [-n mutex name]\n")));
38 ACE_OS::exit (1);
41 // Parse the command-line arguments and set options.
42 static void
43 parse_args (int argc, ACE_TCHAR *argv[])
45 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("dcn:"));
47 int c;
49 while ((c = get_opt ()) != -1)
50 switch (c)
52 case 'd':
53 release_mutex = 0;
54 break;
55 case 'c':
56 child_process = 1;
57 break;
58 case 'n':
59 mutex_name = get_opt.opt_arg ();
60 break;
61 default:
62 print_usage_and_die ();
63 break;
67 static void
68 acquire_release ()
70 ACE_Process_Mutex mutex (mutex_name);
72 // Make sure the constructor succeeded
73 ACE_TEST_ASSERT (ACE_LOG_MSG->op_status () == 0);
75 // To see if we really are the only holder of the mutex below,
76 // we'll try to create a file with exclusive access. If the file
77 // already exists, we're not the only one holding the mutex.
78 ACE_TCHAR mutex_check[MAXPATHLEN+1];
79 ACE_OS::strncpy (mutex_check, mutex_name, MAXPATHLEN);
80 ACE_OS::strncat (mutex_check, ACE_TEXT ("_checker"), MAXPATHLEN);
82 // Grab the lock
83 int mutex_acq = mutex.acquire ();
84 ACE_TEST_ASSERT (mutex_acq == 0);
86 ACE_DEBUG ((LM_DEBUG,
87 ACE_TEXT ("(%P) Mutex acquired %s\n"),
88 mutex_name));
90 ACE_HANDLE checker_handle = ACE_OS::open (mutex_check, O_CREAT | O_EXCL);
91 if (checker_handle == ACE_INVALID_HANDLE)
93 ACE_DEBUG ((LM_WARNING, ACE_TEXT ("(%P): %p\n"),
94 ACE_TEXT ("checker file open")));
95 ACE_TEST_ASSERT (errno != EEXIST);
97 else
98 ACE_OS::close (checker_handle);
100 ACE_DEBUG ((LM_DEBUG,
101 ACE_TEXT ("(%P) Working....\n")));
103 // Do some "work", i.e., just sleep for a couple of seconds.
104 ACE_OS::sleep (2);
106 // Free up the check file for the next acquirer.
107 ACE_OS::unlink (mutex_check);
109 // Check if we need to release the mutex
110 if (release_mutex == 1)
112 ACE_DEBUG ((LM_DEBUG,
113 ACE_TEXT ("(%P) Releasing the mutex %s\n"),
114 mutex_name));
115 int mutex_release = mutex.release ();
116 ACE_TEST_ASSERT (mutex_release == 0);
121 run_main (int argc, ACE_TCHAR *argv[])
123 parse_args (argc, argv);
125 // Child process code.
126 if (child_process)
128 ACE_TCHAR lognm[MAXPATHLEN];
129 int mypid (ACE_OS::getpid ());
130 ACE_OS::snprintf (lognm, MAXPATHLEN,
131 ACE_TEXT ("Process_Mutex_Test-child-%d"), mypid);
133 ACE_START_TEST (lognm);
134 acquire_release ();
135 ACE_END_LOG;
137 else
139 ACE_START_TEST (ACE_TEXT ("Process_Mutex_Test"));
140 # if !defined( ACE_HAS_SYSV_IPC) || defined(ACE_USES_MUTEX_FOR_PROCESS_MUTEX)
141 // When Process_Mutex is pthreads based, then the owner of mutex destroys it
142 // in destructor. This may disturb the other processes which still uses the
143 // mutex. It is safer then to hold the mutex in main process, and destroy it after
144 // children finish. This is temporary solution, and in future pthread base
145 // Process_Mutex shall control the destruction of mutex better.
146 ACE_Process_Mutex mutex( mutex_name );
147 # endif
149 ACE_Process_Options options;
151 #ifndef ACE_LACKS_VA_FUNCTIONS
152 options.command_line (ACE_TEXT ("%") ACE_TEXT_PRIs
153 ACE_TEXT (" -c -n %") ACE_TEXT_PRIs
154 ACE_TEXT ("%") ACE_TEXT_PRIs,
155 argc > 0 ? argv[0] : ACE_TEXT ("Process_Mutex_Test"), mutex_name,
156 release_mutex == 0 ? ACE_TEXT (" -d") : ACE_TEXT (""));
157 #endif
159 #ifdef ACE_HAS_PROCESS_SPAWN
160 // Spawn <n_processes> child processes that will contend for the
161 // lock.
162 ACE_Process children[n_processes];
163 size_t i;
165 for (i = 0;
166 i < n_processes;
167 i++)
169 // Spawn the child process.
170 if (children[i].spawn (options) == -1)
172 ACE_ERROR_RETURN ((LM_ERROR,
173 ACE_TEXT ("spawn of client %d failed\n"),
175 -1);
177 else
179 ACE_DEBUG ((LM_DEBUG,
180 ACE_TEXT ("Parent spawned child process with pid = %d.\n"),
181 children[i].getpid ()));
184 // Give the newly spawned child process a chance to start...
185 // David Levine thinks this sleep() is required because
186 // calling ::waitpid () before a fork'ed child has actually
187 // been created may be a problem on some platforms. It's
188 // not enough for fork() to have returned to the parent.
189 ACE_OS::sleep (1);
192 for (i = 0; i < n_processes; i++)
194 ACE_exitcode child_status;
195 // Wait for the child processes we created to exit.
196 int wait_result = children[i].wait (&child_status);
197 ACE_TEST_ASSERT (wait_result != -1);
198 if (child_status == 0)
199 ACE_DEBUG ((LM_DEBUG,
200 ACE_TEXT ("Child %d finished ok\n"),
201 children[i].getpid ()));
202 else
203 ACE_ERROR ((LM_ERROR,
204 ACE_TEXT ("Child %d finished with status %d\n"),
205 children[i].getpid (), child_status));
208 #endif // ACE_HAS_PROCESS_SPAWN
209 ACE_Process_Mutex::unlink (mutex_name);
210 ACE_END_TEST;
213 return 0;