summaryrefslogtreecommitdiff
path: root/ACE/tests/Process_Mutex_Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/tests/Process_Mutex_Test.cpp')
-rw-r--r--ACE/tests/Process_Mutex_Test.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/ACE/tests/Process_Mutex_Test.cpp b/ACE/tests/Process_Mutex_Test.cpp
new file mode 100644
index 00000000000..76303956767
--- /dev/null
+++ b/ACE/tests/Process_Mutex_Test.cpp
@@ -0,0 +1,218 @@
+// $Id$
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Process_Mutex_Test.cpp
+//
+// = DESCRIPTION
+// Tests an <ACE_Process_Mutex> shared between multiple child processes.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "test_config.h"
+#include "ace/Mutex.h"
+#include "ace/Process.h"
+#include "ace/Process_Mutex.h"
+#include "ace/Get_Opt.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/os_include/os_dirent.h"
+
+
+
+static int release_mutex = 1;
+static int child_process = 0;
+static const ACE_TCHAR *mutex_name = ACE_DEFAULT_MUTEX;
+#if defined (__Lynx__)
+static const u_int n_processes = 4;
+#else /* ! __Lynx__ */
+static const u_int n_processes = ACE_MAX_PROCESSES;
+#endif /* ! __Lynx__ */
+
+// Explain usage and exit.
+static void
+print_usage_and_die (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("usage: %n [-d (don't release mutex)] ")
+ ACE_TEXT ("[-c (child process)] [-n mutex name]\n")));
+ ACE_OS::exit (1);
+}
+
+// Parse the command-line arguments and set options.
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("dcn:"));
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'd':
+ release_mutex = 0;
+ break;
+ case 'c':
+ child_process = 1;
+ break;
+ case 'n':
+ mutex_name = get_opt.opt_arg ();
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+static void
+acquire_release (void)
+{
+ ACE_Process_Mutex mutex (mutex_name);
+
+ // Make sure the constructor succeeded
+ ACE_ASSERT (ACE_LOG_MSG->op_status () == 0);
+
+ // To see if we really are the only holder of the mutex below,
+ // we'll try to create a file with exclusive access. If the file
+ // already exists, we're not the only one holding the mutex.
+ ACE_TCHAR mutex_check[MAXPATHLEN+1];
+ ACE_OS::strncpy (mutex_check, mutex_name, MAXPATHLEN);
+ ACE_OS::strncat (mutex_check, ACE_TEXT ("_checker"), MAXPATHLEN);
+
+ // Grab the lock
+ int mutex_acq = mutex.acquire ();
+ ACE_ASSERT (mutex_acq == 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P) Mutex acquired %s\n"),
+ mutex_name));
+
+ ACE_HANDLE checker_handle = ACE_OS::open (mutex_check, O_CREAT | O_EXCL);
+ if (checker_handle == ACE_INVALID_HANDLE)
+ {
+ ACE_ASSERT (errno != EEXIST);
+ ACE_DEBUG ((LM_WARNING, ACE_TEXT ("(%P): %p\n"),
+ ACE_TEXT ("checker file open")));
+ }
+ else
+ ACE_OS::close (checker_handle);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P) Working....\n")));
+
+ // Do some "work", i.e., just sleep for a couple of seconds.
+ ACE_OS::sleep (2);
+
+ // Free up the check file for the next acquirer.
+ ACE_OS::unlink (mutex_check);
+
+ // Check if we need to release the mutex
+ if (release_mutex == 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P) Releasing the mutex %s\n"),
+ mutex_name));
+ int mutex_release = mutex.release ();
+ ACE_ASSERT (mutex_release == 0);
+ }
+}
+
+int
+run_main (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ // Child process code.
+ if (child_process)
+ {
+ ACE_TCHAR lognm[MAXPATHLEN];
+ int mypid (ACE_OS::getpid ());
+ ACE_OS::sprintf(lognm, ACE_TEXT ("Process_Mutex_Test-child-%d"), mypid);
+
+ ACE_START_TEST (lognm);
+ acquire_release ();
+ ACE_END_LOG;
+ }
+ else
+ {
+ ACE_START_TEST (ACE_TEXT ("Process_Mutex_Test"));
+# if !defined( ACE_HAS_SYSV_IPC) || defined( ACE_USES_MUTEX_FOR_PROCESS_MUTEX )
+ // When Process_Mutex is pthreads based, then the owner of mutex destroys it
+ // in destructor. This may disturb the other processes which still uses the
+ // mutex. It is safer then to hold the mutex in main process, and destroy it after
+ // children finish. This is temporary solution, and in future pthread base
+ // Process_Mutex shall control the destruction of mutex better.
+ ACE_Process_Mutex mutex( mutex_name );
+# endif
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ static const ACE_TCHAR* format = ACE_TEXT ("%ls -c -n %ls%ls");
+#else
+ static const ACE_TCHAR* format = ACE_TEXT ("%s -c -n %s%s");
+#endif /* !ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_Process_Options options;
+ options.command_line (format, argc > 0 ? argv[0] : ACE_TEXT ("Process_Mutex_Test"), mutex_name,
+ release_mutex == 0 ? ACE_TEXT (" -d") : ACE_TEXT (""));
+
+ // Spawn <n_processes> child processes that will contend for the
+ // lock.
+ ACE_Process children[n_processes];
+ size_t i;
+
+ for (i = 0;
+ i < n_processes;
+ i++)
+ {
+ // Spawn the child process.
+ if (children[i].spawn (options) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("spawn of client %d failed\n"),
+ i),
+ -1);
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Parent spawned child process with pid = %d.\n"),
+ children[i].getpid ()));
+ }
+
+ // Give the newly spawned child process a chance to start...
+ // David Levine thinks this sleep() is required because
+ // calling ::waitpid () before a fork'ed child has actually
+ // been created may be a problem on some platforms. It's
+ // not enough for fork() to have returned to the parent.
+ ACE_OS::sleep (1);
+ }
+
+ for (i = 0; i < n_processes; i++)
+ {
+ ACE_exitcode child_status;
+ // Wait for the child processes we created to exit.
+ int wait_result = children[i].wait (&child_status);
+ ACE_ASSERT (wait_result != -1);
+ if (child_status == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Child %d finished ok\n"),
+ children[i].getpid ()));
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Child %d finished with status %d\n"),
+ children[i].getpid (), child_status));
+ }
+
+ ACE_END_TEST;
+ }
+
+ return 0;
+}