static pid_t spawn_child (const ACE_TCHAR *argv0, ACE_Process_Manager &mgr, int sleep_time, int my_process_id) { #if defined (ACE_HAS_WINCE) const ACE_TCHAR *cmdline_format = ACE_TEXT("%s %d"); #elif defined (ACE_WIN32) const ACE_TCHAR *cmdline_format = ACE_TEXT("\"%s\" %s %d"); #elif !defined (ACE_USES_WCHAR) const ACE_TCHAR *cmdline_format = ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT("%s %s %d"); #else const ACE_TCHAR *cmdline_format = ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT("%ls %ls %d"); #endif ACE_Process_Options opts; ACE_TCHAR prio[64]; ACE_TCHAR cmd[16]; if (debug_test) ACE_OS::strcpy (cmd, ACE_TEXT ("-d")); else cmd[0] = ACE_TEXT ('\0'); #if defined (ACE_HAS_WIN32_PRIORITY_CLASS) if (my_process_id == 1) { opts.creation_flags (ABOVE_NORMAL_PRIORITY_CLASS); ACE_OS::snprintf (prio, 64, ACE_TEXT ("and priority 'above normal'")); } else if (my_process_id == 2) { opts.creation_flags (BELOW_NORMAL_PRIORITY_CLASS); ACE_OS::snprintf (prio, 64, ACE_TEXT ("and priority 'below normal'")); } else if (my_process_id == 3) { opts.creation_flags (IDLE_PRIORITY_CLASS); ACE_OS::snprintf (prio, 64, ACE_TEXT ("and priority 'idle'")); } else if (my_process_id == 4) { opts.creation_flags (HIGH_PRIORITY_CLASS); ACE_OS::snprintf (prio, 64, ACE_TEXT ("and priority 'high'")); } else if (my_process_id == 5) { opts.creation_flags (NORMAL_PRIORITY_CLASS); ACE_OS::snprintf (prio, 64, ACE_TEXT ("and priority 'normal'")); } else prio[0] = ACE_TEXT ('\0'); ACE_TCHAR pd [16]; ACE_OS::snprintf (pd, 16, ACE_TEXT (" -p %d"), my_process_id); ACE_OS::strcat (cmd, pd); #else ACE_UNUSED_ARG (my_process_id); prio[0] = ACE_TEXT ('\0'); #endif opts.process_name (argv0); #ifndef ACE_LACKS_VA_FUNCTIONS opts.command_line (cmdline_format, #if !defined (ACE_HAS_WINCE) argv0, #endif /* !ACE_HAS_WINCE */ cmd, sleep_time); #else ACE_UNUSED_ARG (cmdline_format); #endif /* ACE_LACKS_VA_FUNCTIONS */ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Spawning <%s> <%s>\n"), opts.process_name(), opts.command_line_buf ())); pid_t result = mgr.spawn (opts); if (result != ACE_INVALID_PID) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) spawned child: pid %d time %d %s\n"), int (result), sleep_time, prio)); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn failed"))); return result; }
int run_main (int argc, ACE_TCHAR *argv[]) { #if defined (ACE_LACKS_FORK) ACE_UNUSED_ARG (argc); ACE_UNUSED_ARG (argv); ACE_START_TEST (ACE_TEXT ("Process_Semaphore_Test")); ACE_ERROR ((LM_INFO, ACE_TEXT ("fork is not supported on this platform\n"))); ACE_END_TEST; #else parse_args (argc, argv); // Child process code. if (child_process) { ACE_START_TEST (ACE_TEXT ("Process_Semaphore_Test-child")); acquire_release (); ACE_END_LOG; } else { ACE_START_TEST (ACE_TEXT ("Process_Semaphore_Test")); 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_Semaphore_Test") ACE_PLATFORM_EXE_SUFFIX ACE_TEXT (" -c -i %d"), exe_sub_dir.c_str(), iterations); // Spawn a child process that will contend for the // lock. ACE_Process child; // Spawn the child process. int result = child.spawn (options); ACE_TEST_ASSERT (result != -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Parent spawned child process with pid = %d.\n"), child.getpid ())); // start test acquire_release (); ACE_exitcode child_status; // Wait for the child processes we created to exit. ACE_TEST_ASSERT (child.wait (&child_status) != -1); 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)); ACE_END_TEST; } #endif /* ! ACE_LACKS_FORK */ return 0; }
int #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) || defined (ACE_LACKS_FORK) // ACE_HAS_NONSTATIC_OBJECT_MANAGER only allows main to have two // arguments. And on platforms that lack fork (), we can't use spawn. main (int argc, ACE_TCHAR* []) { ACE_UNUSED_ARG (argc); ACE_OS::putenv (ACE_TEXT ("TEST_VALUE_POSITIVE=10.2")); ACE_OS::putenv (ACE_TEXT ("TEST_VALUE_NEGATIVE=-10.2")); #else /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER && ! ACE_LACKS_FORK */ main (int argc, ACE_TCHAR * [], ACE_TCHAR *envp[]) { if (argc == 1) { int status; // No arguments means we're the initial test. ACE_Process_Options options (1); status = options.setenv (envp); ACE_ASSERT (status == 0); options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT ("Env_Value_Test run_as_test")); status = options.setenv (ACE_TEXT ("TEST_VALUE_POSITIVE"), ACE_TEXT ("%s"), ACE_TEXT ("10.2")); ACE_ASSERT (status == 0); status = options.setenv (ACE_TEXT ("TEST_VALUE_NEGATIVE"), ACE_TEXT ("%s"), ACE_TEXT ("-10.2")); ACE_ASSERT (status == 0); ACE_Process p; pid_t result = p.spawn (options); ACE_ASSERT (result != -1); p.wait (); } else #endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER && ! ACE_LACKS_FORK */ { // In this case we're the child ACE_START_TEST (ACE_TEXT ("Env_Value_Test")); TEST_THIS (int, ACE_TEXT ("TEST_VALUE_POSITIVE"), 4, 10); #if !defined (ACE_LACKS_FLOATING_POINT) TEST_THIS (double, ACE_TEXT ("TEST_VALUE_POSITIVE"), -1.0, 10.2); #endif /* ! ACE_LACKS_FLOATING_POINT */ TEST_THIS (long, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (unsigned long, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (short, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (unsigned short, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (int, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 4, -10); #if !defined (ACE_LACKS_FLOATING_POINT) TEST_THIS (double, ACE_TEXT ("TEST_VALUE_NEGATIVE"), -1.0, -10.2); #endif /* ! ACE_LACKS_FLOATING_POINT */ TEST_THIS (long, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, -10L); TEST_THIS (unsigned long, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, (unsigned long) -10); TEST_THIS (short, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, -10); TEST_THIS (unsigned short, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, (unsigned short) -10); const ACE_TCHAR *defstr = ACE_TEXT ("Sarah Cleeland is Two!"); ACE_Env_Value<const ACE_TCHAR *> sval (ACE_TEXT ("This_Shouldnt_Be_Set_Hopefully"), defstr); ACE_ASSERT (ACE_OS::strcmp (sval, defstr) == 0); ACE_END_TEST; } return 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::snprintf (lognm, MAXPATHLEN, 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; #ifndef ACE_LACKS_VA_FUNCTIONS options.command_line (format, argc > 0 ? argv[0] : ACE_TEXT ("Process_Mutex_Test"), mutex_name, release_mutex == 0 ? ACE_TEXT (" -d") : ACE_TEXT ("")); #else ACE_UNUSED_ARG (format); #endif #ifdef ACE_HAS_PROCESS_SPAWN // 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_TEST_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)); } #endif // ACE_HAS_PROCESS_SPAWN ACE_Process_Mutex::unlink (mutex_name); ACE_END_TEST; } return 0; }
static int test_concurrent (const ACE_TCHAR *prog, ACE_MEM_Addr &server_addr) { ACE_DEBUG ((LM_DEBUG, "Testing Multithreaded MEM_Stream\n\n")); int status = 0; client_strategy = ACE_MEM_IO::MT; // Echo_Handler uses this. ACE_Accept_Strategy<Echo_Handler, ACE_MEM_ACCEPTOR> accept_strategy; ACE_Creation_Strategy<Echo_Handler> create_strategy; #if defined (ACE_HAS_THREADS) ACE_Thread_Strategy<Echo_Handler> act_strategy; #else ACE_Reactive_Strategy<Echo_Handler> act_strategy (ACE_Reactor::instance ()); #endif /* ACE_HAS_THREADS */ S_ACCEPTOR acceptor; if (acceptor.open (server_addr, ACE_Reactor::instance (), &create_strategy, &accept_strategy, &act_strategy) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("MEM_Acceptor::accept\n")), 1); // Make sure the MEM_Stream created by the underlying MEM_Acceptor // is capable of passing messages of 1MB. acceptor.acceptor ().init_buffer_size (1024 * 1024); acceptor.acceptor ().mmap_prefix (ACE_TEXT ("MEM_Acceptor_")); acceptor.acceptor ().preferred_strategy (ACE_MEM_IO::MT); ACE_MEM_Addr local_addr; if (acceptor.acceptor ().get_local_addr (local_addr) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("MEM_Acceptor::get_local_addr\n")), 1); u_short sport = local_addr.get_port_number (); #if defined (_TEST_USES_THREADS) ACE_UNUSED_ARG (prog); if (ACE_Thread_Manager::instance ()->spawn_n (NUMBER_OF_MT_CONNECTIONS, connect_client, &sport) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn_n()"))); #else ACE_Process_Options opts; # if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) const ACE_TCHAR *cmdline_fmt = ACE_TEXT ("%s -p%d -m"); # else const ACE_TCHAR *cmdline_fmt = ACE_TEXT ("%ls -p%d -m"); # endif /* ACE_WIN32 || !ACE_USES_WCHAR */ opts.command_line (cmdline_fmt, prog, sport); if (ACE_Process_Manager::instance ()->spawn_n (NUMBER_OF_MT_CONNECTIONS, opts) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn_n()"))); #endif /* _TEST_USES_THREADS */ ACE_Time_Value tv (60, 0); ACE_Reactor::instance ()->run_reactor_event_loop (tv); if (tv == ACE_Time_Value::zero) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reactor::run_event_loop timeout\n"))); status = 1; } else ACE_DEBUG ((LM_DEBUG, "Reactor::run_event_loop finished\n")); #if defined (_TEST_USES_THREADS) if (ACE_Thread_Manager::instance ()->wait () == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait ()"))); #else if (ACE_Process_Manager::instance ()->wait () == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait ()"))); #endif /* _TEST_USES_THREADS */ if (acceptor.close () == -1) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("MEM_Acceptor::close"))); status = 1; } return status; }
int main (int argc, char *argv[]) { // Estabish call backs and socket names. port1 = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT; const char *remotehost = argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST; const u_short port2 = argc > 3 ? ACE_OS::atoi (argv[3]) : port1 + 1; // Providing the fourth command line argument indicates we don't // want to spawn a new process. On Win32, we use this to exec the // new program. if (argc > 4) run_test (port1, remotehost, port2, argv[4]); else { ACE_DEBUG ((LM_DEBUG, "(%P|%t) local port = %d, remote host = %s, remote port = %d\n", port1, remotehost, port2)); ACE_Process_Options options; options.command_line ("%s %d %s %d %c", argv[0], port1, remotehost, port2, 'c'); // This has no effect on NT and will spawn a process that exec // the above run_test function. options.creation_flags (ACE_Process_Options::NO_EXEC); ACE_Process new_process; switch (new_process.spawn (options)) { case -1: return -1; case 0: run_test (port1, remotehost, port2, "peer1"); break; default: run_test (port2, remotehost, port1, "peer2"); new_process.wait (); break; } } return 0; }
Test::Process_ptr Process_Factory::create_new_process (void) { Startup_Callback *startup_callback_impl; ACE_NEW_THROW_EX (startup_callback_impl, Startup_Callback, CORBA::NO_MEMORY ()); PortableServer::ServantBase_var owner_transfer(startup_callback_impl); CORBA::Object_var poa_object = this->orb_->resolve_initial_references("RootPOA"); PortableServer::POA_var root_poa = PortableServer::POA::_narrow (poa_object.in ()); PortableServer::ObjectId_var id = root_poa->activate_object (startup_callback_impl); CORBA::Object_var object = root_poa->id_to_reference (id.in ()); Test::Startup_Callback_var startup_callback = Test::Startup_Callback::_narrow (object.in ()); CORBA::String_var ior = this->orb_->object_to_string (startup_callback.in ()); const ACE_TCHAR* argv[3] = { ACE_TEXT("child"), ACE_TEXT_CHAR_TO_TCHAR(ior.in ()), 0}; ACE_Process_Options options; #if !defined(ACE_WIN32) options.avoid_zombies (1); #endif /* ACE_WIN32 */ options.command_line (argv); ACE_Process child_process; pid_t pid = child_process.spawn (options); if (pid == -1) { ACE_DEBUG ((LM_DEBUG, "(%P|%t) Process_Factory::create_new_process, " " spawn call failed (%d)\n", ACE_ERRNO_GET)); throw Test::Spawn_Failed (); } int process_has_started = 0; Test::Process_var the_process; for (int i = 0; i != 500 && !process_has_started; ++i) { ACE_Time_Value interval (0, 10000); this->orb_->perform_work (interval); process_has_started = startup_callback_impl->process_has_started (the_process.out ()); } try { PortableServer::POA_var poa = startup_callback_impl->_default_POA (); PortableServer::ObjectId_var id = poa->servant_to_id (startup_callback_impl); poa->deactivate_object (id.in ()); } catch (const CORBA::Exception&) { } if (process_has_started == 0) { ACE_DEBUG ((LM_DEBUG, "(%P|%t) Process_Factory::create_new_process, " " timeout while waiting for child\n")); (void) child_process.terminate (); throw Test::Spawn_Failed (); } return the_process._retn (); }
int run_main (int argc, ACE_TCHAR *argv[]) { #if defined (ACE_WIN32) get_base_addrs(); #endif if (argc == 1) { ACE_START_TEST (ACE_TEXT ("Malloc_Test")); ACE_INIT_LOG (ACE_TEXT ("Malloc_Test-child")); init_test (PARENT_BASE_ADDR); ACE_Control_Block::print_alignment_info (); # if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) ACE_PI_Control_Block::print_alignment_info (); # endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ // No arguments means we're the parent process. ACE_Process_Options options (1); #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR) static const ACE_TCHAR* format = ACE_TEXT ("%ls%ls%ls"); #else static const ACE_TCHAR* format = ACE_TEXT ("%s%s%s"); #endif /* !ACE_WIN32 && ACE_USES_WCHAR */ options.command_line (format, EXE_LOCATION, argc > 0 ? argv[0] : ACE_TEXT ("Malloc_Test"), ACE_TEXT (" run_as_test")); MALLOC *myalloc = myallocator (PARENT_BASE_ADDR); Test_Data *data = initialize (myalloc); ACE_TEST_ASSERT (data != 0); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) PARENT allocator at = %@, ") ACE_TEXT ("data allocated at %@\n"), myalloc, data)); myalloc->dump (); int result = myalloc->bind ("foo", data); ACE_TEST_ASSERT (result != -1); ACE_Process p; pid_t pid = p.spawn (options); if (pid == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn")), 1); parent (data); // Synchronize on the exit of the child. result = p.wait (); if (result == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), 1); ACE_TEST_ASSERT (myalloc->ref_counter () == 1); myalloc->remove (); ACE_END_TEST; return 0; } else { // In this case we're the child process. ACE_APPEND_LOG (ACE_TEXT ("Malloc_Test-child")); void *data = 0; MALLOC *myalloc = myallocator (CHILD_BASE_ADDR); int result = myalloc->find ("foo", data); ACE_TEST_ASSERT (result != -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) CHILD allocator at = %@, ") ACE_TEXT ("data allocated at %@\n"), myalloc, data)); myalloc->dump (); child (); myalloc->release (); ACE_END_LOG; return 0; } }
int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { // Ignore SIGPIPE signal on Unix platforms in case // child process (more) terminates before we finish // writing to stdout. #if !defined (ACE_WIN32) ACE_Sig_Action sig_act (SIG_IGN); if (sig_act.register_action (SIGPIPE) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Sig_Action::register_action"), -1); #endif /* ACE_WIN32 */ // Alright, what you want me to do now? if (::parse_args (argc, argv) == -1) return -1; // Can I find the file you want? ACE_HANDLE infile = ACE_OS::open (fname, O_RDONLY); if (infile == ACE_INVALID_HANDLE) ACE_ERROR_RETURN ((LM_DEBUG, "%p\n", fname), -1); ACE_Process new_process; // The ACE_Process_Options does not need to be enclosed in a block // because it does not close the file handles, the ACE_Process closes // them upon destruction. #if !defined (ACE_WIN32) ACE_Process_Options options; if ((use_named_pipe ? ::setup_named_pipes : ::setup_unnamed_pipe) (options) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Error, bailing out!\n"), -1); options.command_line (executable); if (new_process.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n", "test_more", error_number), -1); } // write file to ACE_STDOUT. if (::print_file (infile) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Error, bailing out!\n"), -1); // Close the STDOUT to inform child eof. ACE_OS::close (ACE_STDOUT); #else // We can only pass a file handler directly to child process // otherwise "more" doesn't act quite the way we want. Nonetheless, // if your child process don't need to interact with the terminal, // we can use the exact code for Unixes on NT. ACE_Process_Options options; options.command_line (executable); options.set_handles (infile); if (new_process.spawn (options) == -1) { int error = ACE_OS::last_error (); ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n", "test_more", error), -1); } #endif /* ! ACE_WIN32 */ // Wait till we are done. ACE_exitcode status; new_process.wait (&status); ACE_DEBUG ((LM_DEBUG, "Process exit with status %d\n", status)); ACE_OS::close (infile); return 0; }
int run_main (int argc, ACE_TCHAR *argv[]) { parse_args (argc, argv); if (child_process) { ACE_APPEND_LOG (ACE_TEXT("Pipe_Test-children")); ACE_Pipe a, b, c, d, e; open_pipe (a, "a"); open_pipe (b, "b"); open_pipe (c, "c"); open_pipe (d, "d"); open_pipe (e, "e"); ACE_END_LOG; } else { ACE_START_TEST (ACE_TEXT("Pipe_Test")); ACE_INIT_LOG (ACE_TEXT("Pipe_Test-children")); # if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) const ACE_TCHAR *cmdline_fmt = ACE_TEXT ("%s -c%s"); # else const ACE_TCHAR *cmdline_fmt = ACE_TEXT ("%ls -c%ls"); # endif /* ACE_WIN32 || !ACE_USES_WCHAR */ ACE_Process_Options options; options.command_line (cmdline_fmt, argc > 0 ? argv[0] : ACE_TEXT ("Pipe_Test"), close_pipe == 0 ? ACE_TEXT (" -d") : ACE_TEXT ("")); ACE_exitcode status = 0; for (int i = 0; i < ::iterations; i++) { ACE_Process server; if (server.spawn (options) == -1) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn failed")), -1); } else { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Server forked with pid = %d.\n"), server.getpid ())); } // Wait for the process we just created to exit. server.wait (&status); // Check if child exited without error. if (WIFEXITED (status) != 0 && WEXITSTATUS (status) != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Child of server %d finished with error ") ACE_TEXT ("exit status %d\n"), server.getpid (), WEXITSTATUS (status))); ACE_END_TEST; ACE_OS::exit (WEXITSTATUS (status)); } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Server %d finished\n"), server.getpid ())); } ACE_END_TEST; } return 0; }
int run_main (int argc, ACE_TCHAR *argv[]) { parse_args (argc, argv); // Child process code. if (child_nr >= 0) { ACE_TCHAR lognm[MAXPATHLEN]; int mypid (ACE_OS::getpid ()); ACE_OS::sprintf(lognm, ACE_TEXT ("RW_Process_Mutex_Test-child-%d"), (int)mypid); ACE_START_TEST (lognm); if (child_nr == 0) writer (); else reader (child_nr); ACE_END_LOG; } else { ACE_START_TEST (ACE_TEXT ("RW_Process_Mutex_Test")); // Although it should be safe for each process to construct and // destruct the rw lock, this can disturb other process still // using the lock. This is not really correct, and should be // looked at, but it gets things moving. // Also see Process_Mutex_Test.cpp for similar issue. ACE_RW_Process_Mutex mutex (mutex_name.c_str ()); // Make sure the constructor succeeded if (ACE_LOG_MSG->op_status () != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Parent, mutex %s %p\n"), mutex_name.c_str (), ACE_TEXT ("ctor"))); } #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR) static const ACE_TCHAR* format = ACE_TEXT ("%ls -c %d -p %u -n %ls"); #else static const ACE_TCHAR* format = ACE_TEXT ("%s -c %d -p %u -n %s"); #endif /* !ACE_WIN32 && ACE_USES_WCHAR */ // The parent process reads time ranges sent from the children via // UDP. Grab an unused UDP port to tell the children to send to. ACE_INET_Addr me; ACE_SOCK_Dgram sock; if (sock.open (ACE_Addr::sap_any, PF_INET) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Socket %p\n"), ACE_TEXT ("open")), -1); sock.get_local_addr (me); ACE_TCHAR me_str[80]; me.addr_to_string (me_str, 80); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Receiving on %s\n"), me_str)); // Spawn 1 writer and 3 reader processes that will contend for the // lock. Child writer; Child readers[Nr_Processes - 1]; int i; for (i = 0; i < Nr_Processes; i++) { Child *child = (i == 0 ? &writer : &readers[i-1]); ACE_Process_Options options; options.command_line (format, argc > 0 ? argv[0] : ACE_TEXT ("RW_Process_Mutex_Test"), i, (unsigned int)me.get_port_number (), mutex_name.c_str ()); if (child->spawn (options) == -1) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("spawn of child %d %p\n"), i, ACE_TEXT ("failed")), -1); } else { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Child process %d has pid = %d.\n"), i, (int)(child->getpid ()))); } } // Keep reading time ranges reported from the children until all the // children have exited. Alternate between checking for a range and // checking for exits. int processes = Nr_Processes; Child *children[Nr_Processes]; for (i = 0; i < Nr_Processes; i++) children[i] = (i == 0 ? &writer : &readers[i-1]); Range_Report report; ACE_Time_Value poll (0); ACE_INET_Addr from; ssize_t bytes; while (processes > 0) { ACE_Time_Value limit (10); bytes = sock.recv (&report, sizeof (report), from, 0, &limit); if (bytes > 0) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Report from child %d; %b bytes\n"), report.child_, bytes)); if (report.child_ == 0) writer.add_range (report.range_); else { if (report.child_ >= 1 && report.child_ < Nr_Processes) readers[report.child_ - 1].add_range (report.range_); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("Report from out-of-range child #%d\n"), report.child_)); } } else { if (errno == ETIME) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("UDP time out; check child exits\n"))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("UDP recv"))); } for (i = 0; i < Nr_Processes; i++) { if (children[i] == 0) continue; ACE_exitcode child_status; // See if the child has exited. int wait_result = children[i]->wait (poll, &child_status); if (wait_result == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Wait for child %d, %p\n"), i, ACE_TEXT ("error"))); else if (wait_result != 0) { if (child_status == 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Child %d finished ok\n"), (int)(children[i]->getpid ()))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("Child %d finished with status %d\n"), (int)(children[i]->getpid ()), child_status)); children[i] = 0; --processes; } } } sock.close (); if (0 != mutex.remove ()) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("mutex remove"))); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Comparing time ranges...\n"))); // The writer should never overlap any readers bool writer_overlap = false; for (i = 0; i < Nr_Processes - 1; ++i) { if (writer.any_overlaps (readers[i])) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Writer overlaps reader %d\n"), i+1)); writer_overlap = true; } } if (!writer_overlap) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writer does not overlap with readers; Ok\n"))); // And there should be some overlap between readers. bool reader_overlap = false; for (i = 0; i < Nr_Processes - 1; ++i) { // Just compare to those higher, else it compares the same ones, // only in reverse. for (int j = i + 1; j < Nr_Processes - 1; ++j) { if (readers[i].any_overlaps (readers[j])) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reader %d overlaps reader %d; Ok\n"), i + 1, j + 1)); reader_overlap = true; } } } if (!reader_overlap) ACE_ERROR ((LM_ERROR, ACE_TEXT ("No readers overlapped!\n"))); ACE_END_TEST; } return 0; }
int run_parent (bool inherit_files) { int status = 0; 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"))); status = 1; } // 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) { status = errno; 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) { status = errno; 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 { status = child_status; ACE_ERROR ((LM_ERROR, ACE_TEXT ("Child %d finished with status %d\n"), child.getpid (), child_status)); } return status; }
// Listing 5 // Listing 3 code/ch17 int handle_parent (char *cmdLine) { ACE_TRACE (ACE_TEXT ("::handle_parent")); ALLOCATOR * shmem_allocator = 0; ACE_MMAP_Memory_Pool_Options options (ACE_DEFAULT_BASE_ADDR, ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED); ACE_NEW_RETURN (shmem_allocator, ALLOCATOR (BACKING_STORE, BACKING_STORE, &options), -1); MAP *map = smap (shmem_allocator); ACE_Process processa, processb; ACE_Process_Options poptions; poptions.command_line("%s a", cmdLine); { ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, coordMutex, -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) Map has %d entries\n"), map->current_size ())); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("In parent, map is located at %@\n"), map)); // Then have the child show and eat them up. processa.spawn (poptions); // First append a few records. addRecords (map, shmem_allocator); } { ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, coordMutex, -1); // Add a few more records.. addRecords (map, shmem_allocator); // Let's see what's left. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) Parent finished adding, ") ACE_TEXT ("map has %d entries\n"), map->current_size ())); // Have another child try to eat them up. processb.spawn (poptions); } processa.wait (); processb.wait (); // No processes are left and we don't want to keep the data // around anymore; it's now safe to remove it. // !!This will remove the backing store.!! shmem_allocator->remove (); delete shmem_allocator; return 0; }
int run_main (int argc, ACE_TCHAR *argv[]) { #if defined (ACE_LACKS_FORK) ACE_UNUSED_ARG (argc); ACE_UNUSED_ARG (argv); ACE_START_TEST (ACE_TEXT ("Process_Mutex_Test")); ACE_ERROR ((LM_INFO, ACE_TEXT ("fork is not supported on this platform\n"))); ACE_END_TEST; #else /* ! ACE_LACKS_FORK */ parse_args (argc, argv); // Child process code. if (child_process) { ACE_APPEND_LOG ("Process_Mutex_Test-children"); acquire_release (); ACE_END_LOG; } else { ACE_START_TEST (ACE_TEXT ("Process_Mutex_Test")); ACE_INIT_LOG ("Process_Mutex_Test-children"); ACE_Process_Options options; if (release_mutex == 0) options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT ("Process_Mutex_Test") ACE_PLATFORM_EXE_SUFFIX ACE_TEXT (" -c -n %s -d"), ACE_TEXT_CHAR_TO_TCHAR (mutex_name)); else options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT ("Process_Mutex_Test") ACE_PLATFORM_EXE_SUFFIX ACE_TEXT (" -c -n %s"), ACE_TEXT_CHAR_TO_TCHAR (mutex_name)); // 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. int result = children[i].spawn (options); ACE_ASSERT (result != -1); 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. ACE_ASSERT (children[i].wait (&child_status) != -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; } #endif /* ! ACE_LACKS_FORK */ return 0; }
int // This has been unconditionally turned on for the time being since I can't // figure out an easy way to enable it and still keep ACE_TMAIN in a seperate // cpp. #if 1 || defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) || defined (ACE_LACKS_FORK) // ACE_HAS_NONSTATIC_OBJECT_MANAGER only allows main to have two // arguments. And on platforms that lack fork (), we can't use spawn. run_main (int, ACE_TCHAR* []) { // Only Win32 can set wide-char environment strings. So, for all // others, use char string literals regardless of ACE_USES_WCHAR. # if defined (ACE_WIN32) ACE_OS::putenv (ACE_TEXT ("TEST_VALUE_POSITIVE=10.2")); ACE_OS::putenv (ACE_TEXT ("TEST_VALUE_NEGATIVE=-10.2")); # else ACE_OS::putenv ("TEST_VALUE_POSITIVE=10.2"); ACE_OS::putenv ("TEST_VALUE_NEGATIVE=-10.2"); # endif /* ACE_WIN32 */ #else /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER && ! ACE_LACKS_FORK */ run_main (int argc, ACE_TCHAR * [], ACE_TCHAR *envp[]) { if (argc == 1) { int status; // No arguments means we're the initial test. ACE_Process_Options options (1); status = options.setenv (envp); if (status != 0) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("setenv(envp)"))); options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT ("Env_Value_Test run_as_test")); status = options.setenv (ACE_TEXT ("TEST_VALUE_POSITIVE"), ACE_TEXT ("%s"), ACE_TEXT ("10.2")); if (status != 0) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("setenv(TEST_VALUE_POSITIVE)"))); status = options.setenv (ACE_TEXT ("TEST_VALUE_NEGATIVE"), ACE_TEXT ("%s"), ACE_TEXT ("-10.2")); if (status != 0) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("setenv(TEST_VALUE_NEGATIVE)"))); ACE_Process p; pid_t result = p.spawn (options); if (result == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn"))); else p.wait (); } else #endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER && ! ACE_LACKS_FORK */ { // In this case we're the child ACE_START_TEST (ACE_TEXT ("Env_Value_Test")); TEST_THIS (int, ACE_TEXT ("TEST_VALUE_POSITIVE"), 4, 10); TEST_THIS (double, ACE_TEXT ("TEST_VALUE_POSITIVE"), -1.0, 10.2); TEST_THIS (long, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (unsigned long, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (short, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (unsigned short, ACE_TEXT ("TEST_VALUE_POSITIVE"), 0, 10); TEST_THIS (int, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 4, -10); TEST_THIS (double, ACE_TEXT ("TEST_VALUE_NEGATIVE"), -1.0, -10.2); TEST_THIS (long, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, -10L); TEST_THIS (unsigned long, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, (unsigned long) -10); TEST_THIS (short, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, -10); TEST_THIS (unsigned short, ACE_TEXT ("TEST_VALUE_NEGATIVE"), 0, (unsigned short) -10); const ACE_TCHAR *defstr = ACE_TEXT ("Sarah Cleeland is Two!"); ACE_Env_Value<const ACE_TCHAR *> sval (ACE_TEXT ("This_Shouldnt_Be_Set_Hopefully"), defstr); if (ACE_OS::strcmp (sval, defstr) != 0) ACE_ERROR ((LM_ERROR, ACE_TEXT ("Mismatch: %s should be %s\n"), (const ACE_TCHAR *)sval, defstr)); ACE_END_TEST; } return 0; }