summaryrefslogtreecommitdiff
path: root/ACE/tests/Process_Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/tests/Process_Test.cpp')
-rw-r--r--ACE/tests/Process_Test.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/ACE/tests/Process_Test.cpp b/ACE/tests/Process_Test.cpp
new file mode 100644
index 00000000000..ebf8389a96a
--- /dev/null
+++ b/ACE/tests/Process_Test.cpp
@@ -0,0 +1,233 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Process_Test.cpp
+//
+// = DESCRIPTION
+// Tests ACE_Process file handle inheritance for UNIX-like systems
+//
+// = AUTHOR
+// Christian Fromme <kaner@strace.org>
+//
+// ============================================================================
+
+#include "test_config.h"
+#include "ace/Process.h"
+#include "ace/Get_Opt.h"
+#include "ace/ACE.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Dirent.h"
+#include "ace/SString.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(tests, Process_Test, "$Id$")
+
+// This will only work on Linux. Even UNIX-ish with /proc filesys lacks the
+// 'self' level and link to the opened file name.
+static const char *proc_self_fd = "/proc/self/fd/";
+
+int
+check_temp_file (const ACE_TString &tmpfilename)
+{
+ ACE_DIRENT *dir = 0;
+ ACE_Dirent entr;
+ ACE_stat stat;
+ char filename[MAXPATHLEN + 1];
+
+ ACE_OS::memset (&stat, 0, sizeof (stat));
+ ACE_OS::memset (&entr, 0, sizeof (entr));
+
+ // Loop through /proc/self/fs/
+ if (entr.open (ACE_TEXT_CHAR_TO_TCHAR(proc_self_fd)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Could not open dir %C\n"),
+ proc_self_fd),
+ -1);
+
+ while ((dir = entr.read ()))
+ {
+ ACE_CString fullp = proc_self_fd;
+#if defined (ACE_HAS_TCHAR_DIRENT)
+ fullp += ACE_TEXT_ALWAYS_CHAR(dir->d_name);
+#else
+ fullp += dir->d_name;
+#endif
+
+ if ((ACE_OS::lstat (fullp.c_str (), &stat)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Stat failed for %C\n"),
+ fullp.c_str ()),
+ -1);
+
+ if (S_ISLNK (stat.st_mode))
+ {
+ ssize_t size = 0;
+ if ((size= ACE_OS::readlink (fullp.c_str (),
+ filename,
+ MAXPATHLEN + 1)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Readlink failed for %C\n"),
+ fullp.c_str ()),
+ -1);
+ filename[size] = '\0';
+ if (tmpfilename == ACE_TString (ACE_TEXT_CHAR_TO_TCHAR (filename)))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void
+run_parent (bool inherit_files)
+{
+ ACE_TCHAR t[] = ACE_TEXT ("ace_testXXXXXX");
+
+ // Create tempfile. This will be tested for inheritance.
+ ACE_TCHAR tempfile[MAXPATHLEN + 1];
+
+ if (ACE::get_temp_dir (tempfile, MAXPATHLEN - sizeof (t)) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Could not get temp dir\n")));
+
+ ACE_OS::strcat (tempfile, t);
+
+ ACE_HANDLE file_handle = ACE_OS::mkstemp (tempfile);
+ if (file_handle == ACE_INVALID_HANDLE)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Could not get temp filename\n")));
+
+ // Build child options
+ ACE_TString exe_sub_dir;
+ const char *subdir_env = ACE_OS::getenv ("ACE_EXE_SUB_DIR");
+ if (subdir_env)
+ {
+ exe_sub_dir = ACE_TEXT_CHAR_TO_TCHAR (subdir_env);
+ exe_sub_dir += ACE_DIRECTORY_SEPARATOR_STR;
+ }
+
+ ACE_Process_Options options;
+ options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR
+ ACE_TEXT ("%sProcess_Test")
+ ACE_PLATFORM_EXE_SUFFIX
+ ACE_TEXT (" -c -h %d -f %s"),
+ exe_sub_dir.c_str(),
+ (int)inherit_files,
+ tempfile);
+ options.handle_inheritance (inherit_files); /* ! */
+
+ // Spawn child
+ ACE_Process child;
+
+ pid_t result = child.spawn (options);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Parent could NOT spawn child process\n")));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Parent spawned child process with pid = %d.\n"),
+ child.getpid ()));
+
+ ACE_exitcode child_status;
+ result = child.wait (&child_status);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Could NOT wait on child process\n")));
+ else if (child_status == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Child %d finished ok\n"),
+ child.getpid ()));
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Child %d finished with status %d\n"),
+ child.getpid (), child_status));
+}
+
+int
+run_main (int argc, ACE_TCHAR *argv[])
+{
+ // This test relies on the ability to get a list of open files for a process
+ // and examine each file descriptor to see which file is open, matching
+ // against an expected opened file name. Although most systems provide some
+ // mechanism to do this, the code in this test uses Linux-specific
+ // techniques. Thus, although it is possible to add the code for the
+ // checks on, for example, HP-UX (pstat_getproc, pstat_getpathname) and
+ // AIX (/proc is available, but there's no self and the fds are not links
+ // to the opened file names), the code isn't here at present.
+#if defined (ACE_LACKS_FORK) || defined (ACE_LACKS_READLINK) || !defined(linux)
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ ACE_START_TEST (ACE_TEXT ("Process_Test"));
+ ACE_ERROR ((LM_INFO,
+ ACE_TEXT ("This test is not supported on this platform\n")));
+ ACE_END_TEST;
+#else
+ int c = 0;
+ int handle_inherit = 0; /* Disable inheritance by default */
+ bool ischild = false;
+ ACE_TString temp_file_name;
+
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("ch:f:"));
+
+ while ((c = getopt ()) != -1)
+ switch ((char) c)
+ {
+ case 'c':
+ ischild = true;
+ break;
+ case 'h':
+ handle_inherit = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'f':
+ temp_file_name = getopt.opt_arg ();
+ break;
+ default:
+ // Don't forgive bad options
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Bad option\n")),
+ -1);
+ break;
+ }
+
+ if (ischild)
+ {
+ ACE_TCHAR lognm[MAXPATHLEN];
+ int const mypid (ACE_OS::getpid ());
+ ACE_OS::sprintf(lognm, ACE_TEXT ("Process_Test-child-%d"), mypid);
+
+ ACE_START_TEST (lognm);
+
+ int result = check_temp_file (temp_file_name);
+ // Check descriptor inheritance
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Could not retrieve open files\n")),
+ -1);
+ else if (result == handle_inherit)
+ result = 0;
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Handle inheritance test failed with ")
+ ACE_TEXT ("%d, expected %d\n"), result, handle_inherit));
+ ACE_END_LOG;
+ return result;
+ }
+ else
+ {
+ ACE_START_TEST (ACE_TEXT ("Process_Test"));
+
+ // Test handle inheritance set to true
+ run_parent (true);
+
+ // ... and set to false
+ run_parent (false);
+
+ ACE_END_TEST;
+ }
+#endif /* ! ACE_LACKS_FORK */
+
+ return 0;
+}