/* \brief Just runs automatic tests Function sends a number of datagrams, spawns child thread or process and tries to receive at least one datagram. \retval 0 datagram was received \retval -1 datagram was not received */ int run_auto_test (const ACE_TCHAR *prog_name) { #if defined (ACE_HAS_PROCESS_SPAWN) ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running auto_tests in process mode\n"))); ACE_Process_Options opts; pid_t child_pid; opts.command_line (ACE_TEXT ("%s -p %d -t %d -a -r"), prog_name, dgram_port, dgram_recv_timeout.msec ()); if ((child_pid = ACE_Process_Manager::instance ()->spawn (opts)) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn_n()")), -1); #elif defined (ACE_HAS_THREADS) ACE_UNUSED_ARG (prog_name); ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running auto_tests in thread mode\n"))); if (ACE_Thread_Manager::instance ()->spawn (run_thread_receiver) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn_n ()")), -1); #else ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Cannot run in auto_test mode without fork or threads.\n")), -1); #endif /* defined (ACE_HAS_PROCESS_SPAWN) */ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Sending datagrams on port %d in auto_test mode\n"), dgram_port)); ACE_SOCK_Dgram_Bcast socket; if (socket.open (ACE_Addr::sap_any) != -1) { // send datagrams until child finishes while (1) { send_datagram (socket, dgrams_no--); ACE_Time_Value child_timeout (1); #if defined (ACE_HAS_PROCESS_SPAWN) if (ACE_Process_Manager::instance ()->wait (child_pid, child_timeout, &receiver_exit_code) == child_pid) break; #else /* ACE_HAS_THREADS */ // sleep 1 second or wait for child thread child_timeout += ACE_OS::gettimeofday () ; if (ACE_Thread_Manager::instance ()->wait (&child_timeout) == 0) break; #endif } socket.close (); ACE_DEBUG ((LM_INFO, ACE_TEXT ("Child finished with %d exit code\n"), receiver_exit_code)); } else ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("Cannot open broadcast socket")), -1); return (receiver_exit_code); }
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)); }
static void test_date (void) { ACE_Process_Options options; options.command_line (DATE_PATH); // Try to create a new process running date. ACE_Process new_process; if (new_process.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p errno = %d.\n"), ACE_TEXT ("test_date"), error_number)); return; } ACE_exitcode status; new_process.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process exit with status %d\n"), status)); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("date succeeded.\n"))); }
// This shows how to set handles. static void test_more (void) { ACE_HANDLE infile = ACE_OS::open (print_file, O_RDONLY); if (infile == ACE_INVALID_HANDLE) { ACE_ERROR ((LM_DEBUG, ACE_TEXT ("%p\n"), print_file)); return; } ACE_Process new_process; ACE_Process_Options options; options.command_line (executable); options.set_handles (infile); if (new_process.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p errno = %d.\n"), ACE_TEXT ("test_more"), error_number)); } ACE_exitcode status; new_process.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process exit with status %d\n"), status)); ACE_OS::close (infile); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("More succeeded.\n"))); }
static int command_line_test (void) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing for last character of command line\n"))); int result = 0; const ACE_TCHAR *command = ACE_TEXT ("test Hello"); size_t command_len = ACE_OS::strlen (command); ACE_Process_Options options (1, command_len + 1); #ifndef ACE_LACKS_VA_FUNCTIONS options.command_line (command); #endif ACE_TCHAR * const *procargv = options.command_line_argv (); if (ACE_OS::strcmp (procargv [1], ACE_TEXT ("Hello")) != 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("command_line_test failed: expected \"%s\"; got \"%s\"\n"), ACE_TEXT ("Hello"), procargv [1])); result = 1; } return result; }
int test_setenv (void) { int status = 0; ACE_Process_Options opts; ACE_TCHAR bigval[5010] = ACE_TEXT (""); for (int i = 0; i < 100; ++i) ACE_OS::strcat (bigval, ACE_TEXT ("01234567890123456789012345678901234567890123456789")); #ifndef ACE_LACKS_VA_FUNCTIONS # if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR) const ACE_TCHAR *fmt = ACE_TEXT ("%ls"); # else const ACE_TCHAR *fmt = ACE_TEXT ("%s"); # endif if (0 != opts.setenv (ACE_TEXT ("A"), fmt, bigval)) { status = errno; ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("setenv"))); } else { size_t env_len = ACE_OS::strlen (opts.env_buf ()); if (env_len != 5002) { status = 1; ACE_ERROR ((LM_ERROR, ACE_TEXT ("setenv result should be 5002 chars, not %B\n"), env_len)); } } #endif return status; }
static void test_setenv (const ACE_TCHAR *argv0) { ACE_Process_Options options; // options.setenv ("ACE_PROCESS_TEST", "here's a really large number: %u", 0 - 1); options.setenv (ACE_TEXT ("ACE_PROCESS_TEST= here's a large number %u"), 0 - 1); options.setenv (ACE_TEXT ("ACE_PROCESS_TEST2"), ACE_TEXT ("ophilli")); #if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) options.command_line ("%s -g", argv0); #else options.command_line ("%ls -g", argv0); #endif ACE_Process process; if (process.spawn (options) == -1) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("test_setenv"))); return; } ACE_exitcode status; process.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process exit with status %d\n"), status)); }
static void test_ls (void) { ACE_Process_Options options; #if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) options.command_line (ACE_TEXT ("%s -al"), LS_PATH); #else options.command_line (ACE_TEXT ("%ls -al"), LS_PATH); #endif ACE_Process new_process; if (new_process.spawn (options) == -1) { int error_number = ACE_OS::last_error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p errno = %d.\n"), ACE_TEXT ("test_ls"), error_number)); } ACE_exitcode status; new_process.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process exit with status %d\n"), status)); }
int CC_Start_Cmd::execute(void) { if (excep_) { ACE_OS::printf ("Exception: %s\n", excep_->_rep_id ()); delete excep_; excep_ = 0; return 0; // CC_FAIL } ACE_OS::printf ("Executing start command (script file: %s)\n", cfg_name_); char cmd_line[1024]; int success = ACE_OS::sprintf(&cmd_line[0], "%s -c %s", "./CC_client", cfg_name_); if(success>=1024 || success==-1) ACE_ERROR_RETURN((LM_ERROR, "Creation of process failed: %s\n", cmd_line), 0); ACE_Process new_process; ACE_Process_Options options; options.command_line(ACE_TEXT_CHAR_TO_TCHAR(cmd_line)); if(new_process.spawn(options) == -1) { ACE_ERROR_RETURN((LM_ERROR, "Creation of process failed: %C\n", cmd_line), 0); } return 1; // CC_SUCCESS }
int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { // Estabish call backs and socket names. port1 = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT; const ACE_TCHAR *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 indicate 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 (ACE_TEXT ("%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, ACE_TEXT("peer1")); break; default: run_test (port2, remotehost, port1, ACE_TEXT("peer2")); new_process.wait (); break; } } return 0; }
static pid_t respawn_self (const ACE_TCHAR *myname, int iter, int exit_code) { ACE_Process_Options options; options.command_line ("%s -c -i %d -e %d", myname, iter, exit_code); return ACE_Process_Manager::instance ()->spawn (options); }
int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (argc > 1) // Running as a child. { ACE_OS::sleep (10); } else // Running as a parent. { // Get the processwide process manager. ACE_Process_Manager* pm = ACE_Process_Manager::instance (); // Specify the options for the new processes // to be spawned. ACE_Process_Options options; options.command_line (ACE_TEXT ("%s a"), argv[0]); // Spawn two child processes. pid_t pids[NCHILDREN]; pm->spawn_n (NCHILDREN, options, pids); // Destroy the first child. pm->terminate (pids[0]); // Wait for the child we just terminated. ACE_exitcode status; pm->wait (pids[0], &status); // Get the results of the termination. #if !defined(ACE_WIN32) if (WIFSIGNALED (status) != 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d died because of a signal ") ACE_TEXT ("of type %d\n"), pids[0], WTERMSIG (status))); #else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("The process terminated with exit code %d\n"), status)); #endif /*ACE_WIN32*/ // Wait for all (only one left) of the // children to exit. pm->wait (0); } return 0; }
static int setup_unnamed_pipe (ACE_Process_Options &opt) { // Create an unnamed pipe instance. ACE_Pipe pipe; // Check if the pipe is created successfully. if (pipe.open () == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "pipe.open"), -1); // Setting up pipe between parent and child process. Use the pipe // as child process'es ACE_STDIN. ACE_Process_Options will keep // copies (by dup) of fd's that we pass in. Notice that we have to // specify child process to use ACE_STDOUT for output explicitly // because we'll close it down in the line after. Child process // will use whatever we use to dup2 ACE_STDOUT as its stdout. opt.set_handles (pipe.read_handle (), ACE_STDOUT); // The previous keep a copy of original ACE_STDOUT fd, now we // can replace ACE_STDOUT of parent process to the pipe. ACE_OS::dup2 (pipe.write_handle (), ACE_STDOUT); // Don't forget to close the unused fd. pipe.close (); return 0; }
int launcher_rvgl::_launch(const std::string &host_id) { if (_running) return err_already_running; std::string dir = pref()->get<std::string>("advanced/rvgl_path", ""); std::string params = pref()->get<std::string>("advanced/rvgl_cmdline", ""); if (dir.empty()) { win_registry r(win_registry::id_dplay, "", "Re-Volt"); dir = r.get<std::string>("Path", ""); pref()->set("advanced/rvgl_path", dir.c_str()); } std::string cmd(dir); #ifdef WIN32 cmd += "/rvgl.exe"; #else cmd += "/rvgl"; #endif cmd = "\"" + cmd + "\""; if (!params.empty()) cmd += " " + params; cmd += (host_id.empty() ? " -lobby" : " -lobby " + host_id); //printf("%s\n", cmd.c_str()); ACE_DEBUG((LM_DEBUG, "launcher_rvgl: command line: %s\n", cmd.c_str())); // Launch options ACE_Process_Manager *pm = ACE_Process_Manager::instance(); ACE_Process_Options opts; opts.working_directory(dir.c_str()); opts.command_line(cmd.c_str()); _rvgl_pid = pm->spawn(opts, this); ACE_DEBUG((LM_INFO, "launcher_rvgl: pid %d from thread %t, cmd: %s\n", _rvgl_pid, cmd.c_str())); if (_rvgl_pid == ACE_INVALID_PID) { ACE_ERROR((LM_ERROR, "launcher_rvgl: failed to launch: %s\n", cmd.c_str())); return err_could_not_launch; } _running = true; return 0; }
bool Service_Manager::run_realmd() { ACE_ARGV realmd_args; realmd_args.add(this->args.argv()[0]); realmd_args.add("runrealmd"); ACE_Process_Manager* pmgr = ACE_Process_Manager::instance(); ACE_Process_Options pop; pop.command_line(realmd_args.argv()); pid_t realmpid = pmgr->spawn(pop); if (realmpid == ACE_INVALID_PID) return false; ServiceInfo *si = new ServiceInfo(realmpid); this->svcs.insert(std::pair<MorpheusServices, ServiceInfo*>(LOGINSERVER, si)); ACE_DEBUG((LM_DEBUG,"Realmd runs at pid %u\n", realmpid)); return true; }
bool Service_Manager::run_proxyd() { ACE_ARGV proxyd_args; proxyd_args.add(this->args.argv()[0]); proxyd_args.add("rungamed"); ACE_Process_Manager* pmgr = ACE_Process_Manager::instance(); ACE_Process_Options pop; pop.command_line(proxyd_args.argv()); pid_t proxyd_pid = pmgr->spawn(pop); if (proxyd_pid == ACE_INVALID_PID) return false; ServiceInfo* si = new ServiceInfo(proxyd_pid); this->svcs.insert(std::pair<MorpheusServices, ServiceInfo*>(GAMESERVER, si)); ACE_DEBUG((LM_DEBUG,"Proxyd runs at pid %u\n", proxyd_pid)); return true; }
// Listing 10 code/ch10 int setUserID (ACE_Process_Options &options) { ACE_TRACE ("Manager::setUserID"); passwd* pw = ACE_OS::getpwnam ("nobody"); if (pw == 0) return -1; options.seteuid (pw->pw_uid); return 0; }
int setStdHandles (ACE_Process_Options &options) { ACE_TRACE ("Manager::setStdHandles"); ACE_OS::unlink ("output.dat"); this->outputfd_ = ACE_OS::open ("output.dat", O_RDWR | O_CREAT); return options.set_handles (ACE_STDIN, ACE_STDOUT, this->outputfd_); }
int Handle_Events::serve (char *buf) { ACE_ARGV arguments (buf); if (ACE_OS::strcmp (arguments[0], TESTER) == 0) { ACE_Process_Options po; ACE_Process p; po.set_handles (ACE_INVALID_HANDLE, OUTPUT_FILE, OUTPUT_FILE); po.command_line (arguments.argv ()); p.spawn (po); return 0; } else return -1; }
static double prof_ace_process (size_t iteration) { if (iteration != 0) { ACE_Process_Options popt; ACE_Process aProcess; popt.command_line (SUBPROGRAM); iteration *= MULTIPLY_FACTOR; if (do_exec_after_fork == 0) popt.creation_flags (ACE_Process_Options::NO_EXEC); ACE_Profile_Timer ptimer; ACE_Profile_Timer::ACE_Elapsed_Time et; double time = 0; pid_t result; for (size_t c = 0; c < iteration; c++) { ACE_STOP_SIGN; ptimer.start (); result = aProcess.spawn (popt); ptimer.stop (); if (result == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "process.spawn"), -1); else if (do_exec_after_fork == 0 && result == 0) ACE_OS::exit (0) ; else { ptimer.elapsed_time (et); time += et.real_time; } } return time / iteration; } else return -1.0; }
int Iterator_Handler::spawn_viewer (void) { char viewer[BUFSIZ]; if (this->get_viewer (viewer, sizeof viewer) != 0) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Problem determining which external ") ACE_TEXT ("viewer to use.\n")), -1); // Set up the command line that will be used when spawning the // external viewer. ACE_Process_Options opts; opts.command_line (ACE_TEXT ("%s %s"), viewer, this->file_.get_path_name ()); pid_t result = ACE_Process_Manager::instance ()->spawn (opts); switch (result) { case 0: // Child return 0; case ACE_INVALID_PID: ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Error during viewer spawn of %p\n"), opts.command_line_buf ()), -1); default: // Parent ACE_DEBUG ((LM_INFO, ACE_TEXT ("Spawned viewer <%s> with PID <%d>.\n"), viewer, result)); break; } return 0; }
int main(int argc, char *argv[]) { ACE_Process_Options options; FILE *fp = 0; char *n_env = 0; int n; if (argc == 1) { n_env = ACE_OS::getenv("FACTORIAL"); n = n_env == 0 ? 10 : atoi(n_env); options.command_line("%s %d", argv[0], n - 1); const char *working_dir = ACE_OS::getenv("WORKING_DIR"); if (working_dir) options.working_directory(working_dir); fp = fopen("factorial.log", "a"); cout << "before setenv" << endl; options.setenv("PROGRAM=%s", ACE::basename(argv[0])); cout << "after setenv" << endl; } else { fp = fopen("factorial.log", "a"); if (atoi(argv[1]) == 1) { fprintf(fp, "[%s|%d]: base case\n", ACE_OS::getenv("PROGRAM"), ACE_OS::getpid()); fclose(fp); return 1; } else { n = atoi(argv[1]); options.command_line("%s %d", argv[0], n - 1); } } ACE_Process child; child.spawn(options); child.wait(); int factorial = n * child.return_value(); fprintf(fp, "[%s|%d]: %d! == %d\n", ACE_OS::getenv("PROGRAM"), ACE_OS::getpid(), n, factorial); fclose(fp); return factorial; }
int main(int argc, char *argv[]) { ACE_Process_Options options; char *n_env = 0; int n; if (argc == 1) { n_env = ACE_OS::getenv("FACTORIAL"); n = n_env == 0 ? 10 : atoi(n_env); options.command_line("%s %d", argv[0], n - 1); } else if (atoi(argv[1]) == 1) { return 1; } else { n = atoi(argv[1]); options.command_line("%s %d", argv[0], n - 1); } ACE_Process child; child.spawn(options); child.wait(); return n * child.return_value(); }
// Listing 2 code/ch10 // prepare() is inherited from ACE_Process. int prepare (ACE_Process_Options &options) { ACE_TRACE ("Manager::prepare"); options.command_line (ACE_TEXT ("%s 1"), this->programName_); if (this->setStdHandles (options) == -1 || this->setEnvVariable (options) == -1) return -1; #if !defined (ACE_WIN32) && !defined (ACE_LACKS_PWD_FUNCTIONS) return this->setUserID (options); #else return 0; #endif }
static int setup_named_pipes (ACE_Process_Options &opt) { // Create a unique temporary name for named pipe. ACE_TCHAR *rendezvous = ACE_OS::tempnam (rendezvous_dir, rendezvous_pfx); // Out of memory? if (rendezvous == 0) return -1; // Alright, this is indeed strange. Named pipes are meant to be // used for unrelated processes. Because of the constraints in // ACE_Process, I have to pre-open the named pipes here. ACE_FIFO_Recv rfifo; // read end fifo. ACE_FIFO_Send wfifo; // write end fifo. // Check if the pipes are created successfully. if (rfifo.open (rendezvous) == -1 || wfifo.open (rendezvous) == -1) { ACE_OS::free (rendezvous); ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "fifo.open"), -1); } // Remove (rm, del) the file after no one uses it any more. ACE_OS::unlink (rendezvous); ACE_OS::free (rendezvous); // Setting up pipe between parent and child process. Use the read // end of the named pipe as child process'es ACE_STDIN. // ACE_Process_Options will keep copies (by dup) of fd's that we // pass in. Notice that we have to specify child process to use // ACE_STDOUT for output explicitly because we'll close it down in // the line after. Child process will use whatever we use to dup2 // ACE_STDOUT as its stdout. opt.set_handles (rfifo.get_handle (), ACE_STDOUT); // The previous keep a copy of original ACE_STDOUT fd, now we // can replace ACE_STDOUT of parent process to the write end // of the named pipe. ACE_OS::dup2 (wfifo.get_handle (), ACE_STDOUT); // Close unused fd's. Notice ACE_FIFO doesn't close the fd // when it goes out of scope. rfifo.close (); wfifo.close (); 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; }
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 (); }
pid_t ACE_Process::spawn (ACE_Process_Options &options) { if (this->prepare (options) < 0) return ACE_INVALID_PID; // Stash the passed/duped handle sets away in this object for later // closing if needed or requested. At the same time, figure out which // ones to include in command line options if that's needed below. ACE_Handle_Set *set_p = 0; if (options.dup_handles (this->dup_handles_)) set_p = &this->dup_handles_; else if (options.passed_handles (this->handles_passed_)) set_p = &this->handles_passed_; // If we are going to end up running a new program (i.e. Win32, or // NO_EXEC option is set) then get any handles passed in the options, // and tack them onto the command line with +H <handle> options, // unless the command line runs out of space. // Note that we're using the knowledge that all the options, argvs, etc. // passed to the options are all sitting in the command_line_buf. Any // call to get the argv then splits them out. So, regardless of the // platform, tack them all onto the command line buf and take it // from there. if (set_p && !ACE_BIT_ENABLED (options.creation_flags (), ACE_Process_Options::NO_EXEC)) { int maxlen = 0; ACE_TCHAR *cmd_line_buf = options.command_line_buf (&maxlen); size_t max_len = static_cast<size_t> (maxlen); size_t curr_len = ACE_OS::strlen (cmd_line_buf); ACE_Handle_Set_Iterator h_iter (*set_p); // Because the length of the to-be-formatted +H option is not // known, and we don't have a snprintf, guess at the space // needed (20 chars), and use that as a limit. for (ACE_HANDLE h = h_iter (); h != ACE_INVALID_HANDLE && curr_len + 20 < max_len; h = h_iter ()) { #if defined (ACE_WIN32) # if defined (ACE_WIN64) curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len], ACE_TEXT (" +H %I64p"), h); # else curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len], ACE_TEXT (" +H %p"), h); # endif /* ACE_WIN64 */ #else curr_len += ACE_OS::sprintf (&cmd_line_buf[curr_len], ACE_TEXT (" +H %d"), h); #endif /* ACE_WIN32 */ } } #if defined (ACE_HAS_WINCE) // Note that WinCE does not have process name included in the command line as argv[0] // like other OS environment. Therefore, it is user's whole responsibility to call // 'ACE_Process_Options::process_name(const ACE_TCHAR *name)' to set the proper // process name (the execution file name with path if needed). BOOL fork_result = ACE_TEXT_CreateProcess (options.process_name(), options.command_line_buf(), options.get_process_attributes(), // must be NULL in CE options.get_thread_attributes(), // must be NULL in CE options.handle_inheritance(), // must be false in CE options.creation_flags(), // must be NULL in CE options.env_buf(), // environment variables, must be NULL in CE options.working_directory(), // must be NULL in CE options.startup_info(), // must be NULL in CE &this->process_info_); if (fork_result) { parent (this->getpid ()); return this->getpid (); } return ACE_INVALID_PID; #elif defined (ACE_WIN32) void* env_buf = options.env_buf (); DWORD flags = options.creation_flags (); # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR) wchar_t* wenv_buf = 0; if (options.use_unicode_environment ()) { wenv_buf = this->convert_env_buffer (options.env_buf ()); env_buf = wenv_buf; flags |= CREATE_UNICODE_ENVIRONMENT; } # endif BOOL fork_result = ACE_TEXT_CreateProcess (0, options.command_line_buf (), options.get_process_attributes (), options.get_thread_attributes (), options.handle_inheritance (), flags, env_buf, // environment variables options.working_directory (), options.startup_info (), &this->process_info_); # if defined (ACE_HAS_WCHAR) && !defined (ACE_USES_WCHAR) if (options.use_unicode_environment ()) delete wenv_buf; # endif if (fork_result) { parent (this->getpid ()); return this->getpid (); } return ACE_INVALID_PID; #elif defined(ACE_OPENVMS) if (ACE_BIT_ENABLED (options.creation_flags (), ACE_Process_Options::NO_EXEC)) ACE_NOTSUP_RETURN (ACE_INVALID_PID); int saved_stdin = ACE_STDIN; int saved_stdout = ACE_STDOUT; int saved_stderr = ACE_STDERR; // Save STD file descriptors and redirect if (options.get_stdin () != ACE_INVALID_HANDLE) { if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF) ACE_OS::exit (errno); if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1) ACE_OS::exit (errno); } if (options.get_stdout () != ACE_INVALID_HANDLE) { if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF) ACE_OS::exit (errno); if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1) ACE_OS::exit (errno); } if (options.get_stderr () != ACE_INVALID_HANDLE) { if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF) ACE_OS::exit (errno); if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1) ACE_OS::exit (errno); } if (options.working_directory () != 0) ACE_NOTSUP_RETURN (ACE_INVALID_PID); this->child_id_ = vfork(); if (this->child_id_ == 0) { ACE_OS::execvp (options.process_name (), options.command_line_argv ()); // something went wrong this->child_id_ = ACE_INVALID_PID; } // restore STD file descriptors (if necessary) if (options.get_stdin () != ACE_INVALID_HANDLE) { if (saved_stdin == -1) ACE_OS::close (ACE_STDIN); else ACE_OS::dup2 (saved_stdin, ACE_STDIN); } if (options.get_stdout () != ACE_INVALID_HANDLE) { if (saved_stdout == -1) ACE_OS::close (ACE_STDOUT); else ACE_OS::dup2 (saved_stdout, ACE_STDOUT); } if (options.get_stderr () != ACE_INVALID_HANDLE) { if (saved_stderr == -1) ACE_OS::close (ACE_STDERR); else ACE_OS::dup2 (saved_stderr, ACE_STDERR); } return this->child_id_; #elif defined (ACE_VXWORKS) && defined (__RTP__) if (ACE_BIT_ENABLED (options.creation_flags (), ACE_Process_Options::NO_EXEC)) ACE_NOTSUP_RETURN (ACE_INVALID_PID); if (options.working_directory () != 0) ACE_NOTSUP_RETURN (ACE_INVALID_PID); int saved_stdin = ACE_STDIN; int saved_stdout = ACE_STDOUT; int saved_stderr = ACE_STDERR; // Save STD file descriptors and redirect if (options.get_stdin () != ACE_INVALID_HANDLE) { if ((saved_stdin = ACE_OS::dup (ACE_STDIN)) == -1 && errno != EBADF) ACE_OS::exit (errno); if (ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1) ACE_OS::exit (errno); } if (options.get_stdout () != ACE_INVALID_HANDLE) { if ((saved_stdout = ACE_OS::dup (ACE_STDOUT)) == -1 && errno != EBADF) ACE_OS::exit (errno); if (ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1) ACE_OS::exit (errno); } if (options.get_stderr () != ACE_INVALID_HANDLE) { if ((saved_stderr = ACE_OS::dup (ACE_STDERR)) == -1 && errno != EBADF) ACE_OS::exit (errno); if (ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1) ACE_OS::exit (errno); } // Wide-char builds need narrow-char strings for commandline and // environment variables. # if defined (ACE_USES_WCHAR) wchar_t * const *wargv = options.command_line_argv (); size_t vcount, i; for (vcount = 0; wargv[vcount] != 0; ++vcount) ; char **procargv = new char *[vcount + 1]; // Need 0 at the end procargv[vcount] = 0; for (i = 0; i < vcount; ++i) procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]); char **procenv = 0; if (options.inherit_environment ()) { wargv = options.env_argv (); for (vcount = 0; wargv[vcount] != 0; ++vcount) ; procenv = new char *[vcount + 1]; // Need 0 at the end procenv[vcount] = 0; for (i = 0; i < vcount; ++i) procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]); } # else const char **procargv = const_cast<const char**> (options.command_line_argv ()); const char **procenv = const_cast<const char**> (options.env_argv ()); # endif /* ACE_USES_WCHAR */ this->child_id_ = ::rtpSpawn (procargv[0], procargv, procenv, 200, // priority 0x10000, // uStackSize 0, // options VX_FP_TASK); // taskOptions int my_errno_ = errno; if (this->child_id_ == ERROR) { // something went wrong this->child_id_ = ACE_INVALID_PID; } # if defined (ACE_USES_WCHAR) if (procenv) delete procenv; # endif /* ACE_USES_WCHAR */ // restore STD file descriptors (if necessary) if (options.get_stdin () != ACE_INVALID_HANDLE) { if (saved_stdin == -1) ACE_OS::close (ACE_STDIN); else ACE_OS::dup2 (saved_stdin, ACE_STDIN); } if (options.get_stdout () != ACE_INVALID_HANDLE) { if (saved_stdout == -1) ACE_OS::close (ACE_STDOUT); else ACE_OS::dup2 (saved_stdout, ACE_STDOUT); } if (options.get_stderr () != ACE_INVALID_HANDLE) { if (saved_stderr == -1) ACE_OS::close (ACE_STDERR); else ACE_OS::dup2 (saved_stderr, ACE_STDERR); } if (this->child_id_ == ACE_INVALID_PID) { errno = my_errno_; } return this->child_id_; #else /* ACE_WIN32 */ // Fork the new process. this->child_id_ = ACE::fork (options.process_name (), options.avoid_zombies ()); if (this->child_id_ == 0) { # if !defined (ACE_LACKS_SETPGID) // If we're the child and the options specified a non-default // process group, try to set our pgid to it. This allows the // <ACE_Process_Manager> to wait for processes by their // process-group. if (options.getgroup () != ACE_INVALID_PID && ACE_OS::setpgid (0, options.getgroup ()) < 0) { #if !defined (ACE_HAS_THREADS) // We can't emit this log message because ACE_ERROR(), etc. // will invoke async signal unsafe functions, which results // in undefined behavior in threaded programs. ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("ACE_Process::spawn: setpgid failed."))); #endif } # endif /* ACE_LACKS_SETPGID */ # if !defined (ACE_LACKS_SETREGID) if (options.getrgid () != (uid_t) -1 || options.getegid () != (uid_t) -1) if (ACE_OS::setregid (options.getrgid (), options.getegid ()) == -1) { #if !defined (ACE_HAS_THREADS) // We can't emit this log message because ACE_ERROR(), etc. // will invoke async signal unsafe functions, which results // in undefined behavior in threaded programs. ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("ACE_Process::spawn: setregid failed."))); #endif } # endif /* ACE_LACKS_SETREGID */ # if !defined (ACE_LACKS_SETREUID) // Set user and group id's. if (options.getruid () != (uid_t) -1 || options.geteuid () != (uid_t) -1) if (ACE_OS::setreuid (options.getruid (), options.geteuid ()) == -1) { #if !defined (ACE_HAS_THREADS) // We can't emit this log message because ACE_ERROR(), etc. // will invoke async signal unsafe functions, which results // in undefined behavior in threaded programs. ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("ACE_Process::spawn: setreuid failed."))); #endif } # endif /* ACE_LACKS_SETREUID */ this->child (ACE_OS::getppid ()); } else if (this->child_id_ != -1) this->parent (this->child_id_); // If we're not supposed to exec, return the process id. if (ACE_BIT_ENABLED (options.creation_flags (), ACE_Process_Options::NO_EXEC)) return this->child_id_; switch (this->child_id_) { case -1: // Error. return ACE_INVALID_PID; case 0: // Child process...exec the { if (options.get_stdin () != ACE_INVALID_HANDLE && ACE_OS::dup2 (options.get_stdin (), ACE_STDIN) == -1) ACE_OS::exit (errno); else if (options.get_stdout () != ACE_INVALID_HANDLE && ACE_OS::dup2 (options.get_stdout (), ACE_STDOUT) == -1) ACE_OS::exit (errno); else if (options.get_stderr () != ACE_INVALID_HANDLE && ACE_OS::dup2 (options.get_stderr (), ACE_STDERR) == -1) ACE_OS::exit (errno); // close down unneeded descriptors ACE_OS::close (options.get_stdin ()); ACE_OS::close (options.get_stdout ()); ACE_OS::close (options.get_stderr ()); if (!options.handle_inheritance ()) { // Set close-on-exec for all FDs except standard handles for (int i = ACE::max_handles () - 1; i >= 0; i--) { if (i == ACE_STDIN || i == ACE_STDOUT || i == ACE_STDERR) continue; ACE_OS::fcntl (i, F_SETFD, FD_CLOEXEC); } } // If we must, set the working directory for the child // process. if (options.working_directory () != 0) ACE_OS::chdir (options.working_directory ()); // Should check for error here! // Child process executes the command. int result = 0; // Wide-char builds not on Windows need narrow-char strings for // exec() and environment variables. Don't need to worry about // releasing any of the converted string memory since this // process will either exec() or exit() shortly. # if defined (ACE_USES_WCHAR) ACE_Wide_To_Ascii n_procname (options.process_name ()); const char *procname = n_procname.char_rep (); wchar_t * const *wargv = options.command_line_argv (); size_t vcount, i; for (vcount = 0; wargv[vcount] != 0; ++vcount) ; char **procargv = new char *[vcount + 1]; // Need 0 at the end procargv[vcount] = 0; for (i = 0; i < vcount; ++i) procargv[i] = ACE_Wide_To_Ascii::convert (wargv[i]); wargv = options.env_argv (); for (vcount = 0; wargv[vcount] != 0; ++vcount) ; char **procenv = new char *[vcount + 1]; // Need 0 at the end procenv[vcount] = 0; for (i = 0; i < vcount; ++i) procenv[i] = ACE_Wide_To_Ascii::convert (wargv[i]); # else const char *procname = options.process_name (); char *const *procargv = options.command_line_argv (); char *const *procenv = options.env_argv (); # endif /* ACE_USES_WCHAR */ if (options.inherit_environment ()) { // Add the new environment variables to the environment // context of the context before doing an <execvp>. for (size_t i = 0; procenv[i] != 0; i++) if (ACE_OS::putenv (procenv[i]) != 0) return ACE_INVALID_PID; // Now the forked process has both inherited variables and // the user's supplied variables. result = ACE_OS::execvp (procname, procargv); } else { result = ACE_OS::execve (procname, procargv, procenv); } if (result == -1) { // If the execv fails, this child needs to exit. // Exit with the errno so that the calling process can // catch this and figure out what went wrong. ACE_OS::_exit (errno); } // ... otherwise, this is never reached. return 0; } default: // Server process. The fork succeeded. return this->child_id_; } #endif /* ACE_WIN32 */ }
int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (ACE_LOG_MSG->open (argv[0]) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("cannot open logger!!!\n"))); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("starting...\n"))); if (::parse_args (argc, argv) == -1) return -1; if (run_all) { #if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) const ACE_TCHAR *cmdline = ACE_TEXT ("%s -d -l -s -w"); #else const ACE_TCHAR *cmdline = ACE_TEXT ("%ls -d -l -s -w"); #endif ACE_Process_Options options; options.command_line (cmdline, argv[0]); ACE_Process process; if (process.spawn (options) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p.\n"), ACE_TEXT ("main")), -1); ACE_exitcode status; process.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process exit with status %d\n"), status)); } if (run_date) ::test_date (); if (run_setenv) ::test_setenv (argv[0]); if (get_env) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("checking ACE_PROCESS_TEST\n"))); char *value = ACE_OS::getenv ("ACE_PROCESS_TEST"); char *value2 = ACE_OS::getenv ("ACE_PROCESS_TEST2"); ACE_DEBUG ((LM_DEBUG, "ACE_PROCESS_TEST = %C.\n" "ACE_PROCESS_TEST2 = %C.\n", value == 0 ? "no value" : value, value2 == 0 ? "no value" : value2)); } if (run_ls) ::test_ls (); if (run_wait) ::test_wait (); #if defined (ACE_WIN32) ACE_UNUSED_ARG (&win32_test_ls); if (environment_string != 0) win32_spawn_environment_process (); #endif /* ACE_WIN32 */ if (print_file != 0) test_more (); ACE_TCHAR buf1[30]; ACE_TCHAR buf2[30]; ACE_OS::strcpy(buf1, ACE_TEXT (" -f hi honey -g \"I\'m home\"")); ACE_OS::strcpy(buf2, ACE_TEXT ("\"token 1\"\'token 2\'\"token 3\" ")); if (run_tokenizer) { tokenize (buf1); tokenize (buf2); } return 0; }
static void test_wait (void) { ACE_Process_Options options; #if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) options.command_line (ACE_TEXT ("%s 10"), SLEEP_PATH); #else options.command_line (ACE_TEXT ("%ls 10"), SLEEP_PATH); #endif ACE_Process process1; if (process1.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p errno = %d.\n"), ACE_TEXT ("test_ls"), error_number)); } int result; ACE_exitcode status; //FUZZ: disable check_for_lack_ACE_OS ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%T] New process sleeping 10; try wait(2)\n"))); //FUZZ: enable check_for_lack_ACE_OS result = process1.wait (ACE_Time_Value (2), &status); //FUZZ: disable check_for_lack_ACE_OS ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%T] wait(2) returns %d(%d)...now try regular wait\n"), result, status)); //FUZZ: enable check_for_lack_ACE_OS result = process1.wait (&status); //FUZZ: disable check_for_lack_ACE_OS ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%T] wait() returns %d(%d)\n"), result, status)); //FUZZ: enable check_for_lack_ACE_OS ACE_Process process2; if (process2.spawn (options) == -1) { int const error_number = ACE_OS::last_error (); ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p errno = %d.\n"), ACE_TEXT ("test_ls"), error_number)); } //FUZZ: disable check_for_lack_ACE_OS ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%T] New process sleeping 10; try wait(12)\n"), status)); //FUZZ: enable check_for_lack_ACE_OS result = process2.wait (ACE_Time_Value (12), &status); //FUZZ: disable check_for_lack_ACE_OS ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%T] wait(12) returns %d(%d)...now try regular wait\n"), result, status)); //FUZZ: enable check_for_lack_ACE_OS result = process2.wait (&status); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%T] wait returns %d(%d)\n"), result, status)); }