Beispiel #1
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, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Time_Service_Test"));

  // Make sure that the backing store is not there. We need to make
  // sure because this test kills the Time Clerk and on some platforms
  // the Clerk is not allowed to do a graceful shutdown. By cleaning
  // the backing store here, we are sure that we get a fresh start and
  // no garbage data from a possible aborted run
  ACE_TCHAR backing_store[MAXPATHLEN + 1];

#if defined (ACE_DEFAULT_BACKING_STORE)
  // Create a temporary file.
  ACE_OS::strcpy (backing_store,
                  ACE_DEFAULT_BACKING_STORE);
#else /* ACE_DEFAULT_BACKING_STORE */
  if (ACE::get_temp_dir (backing_store,
                         MAXPATHLEN - 17) == -1) // -17 for ace-malloc-XXXXXX
    {
      ACE_ERROR ((LM_ERROR,
                  ACE_TEXT ("Temporary path too long, ")
                  ACE_TEXT ("defaulting to current directory\n")));
      backing_store[0] = 0;
    }

  // Add the filename to the end
  ACE_OS::strcat (backing_store,
                         ACE_TEXT ("ace-malloc-XXXXXX"));

#endif /* ACE_DEFAULT_BACKING_STORE */

  ACE_OS::unlink (backing_store);

  const ACE_TCHAR *server_cl = APPLICATION ACE_TEXT ("server.conf");
  ACE_Process_Options server_options;
  server_options.command_line (server_cl);
  ACE_Process server;

  if (server.spawn (server_options) == -1)
    ACE_ERROR_RETURN ((LM_DEBUG,
                       ACE_TEXT ("%n; %p (%s).\n"),
                       ACE_TEXT ("Server fork failed"),
                       server_cl),
                      -1);
  else
    ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("Server forked with pid = %d.\n"),
                server.getpid ()));

  ACE_OS::sleep (3);

  const ACE_TCHAR *clerk_cl = APPLICATION ACE_TEXT ("clerk.conf");
  ACE_Process_Options clerk_options;
  clerk_options.command_line (clerk_cl);
  ACE_Process clerk;

  if (clerk.spawn (clerk_options) == -1)
    ACE_ERROR_RETURN ((LM_DEBUG, ACE_TEXT ("%n; %p: (%s).\n"),
                       ACE_TEXT ("Clerk fork failed"), clerk_cl), -1);
  else
    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Clerk forked with pid = %d.\n"),
                clerk.getpid ()));

  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Sleeping...\n")));
  ACE_OS::sleep (10);

  if (clerk.terminate () == -1)
    ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Terminate failed for clerk.\n")),
                      -1);

  if (server.terminate () == -1)
    ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Terminate failed for server.\n")),
                      -1);

  // Because we kill the clerk process, on Win32 it may not do a
  // graceful shutdown and the backing store file is left behind.
  if (clerk.wait () != 0)
    ACE_OS::unlink (backing_store);

  ACE_END_TEST;
  return 0;
}
Beispiel #3
0
pid_t
ACE_Process_Manager::wait (pid_t pid,
                           const ACE_Time_Value &timeout,
                           ACE_exitcode *status)
{
  ACE_TRACE ("ACE_Process_Manager::wait");

  ACE_exitcode local_stat = 0;
  if (status == 0)
    status = &local_stat;

  *status = 0;

  ssize_t idx = -1;
  ACE_Process *proc = 0;

  {
    // fake context after which the lock is released
    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));

    if (pid != 0)
      {
        idx = this->find_proc (pid);
        if (idx == -1)
          return ACE_INVALID_PID;
        else
          proc = process_table_[idx].process_;
      }
    // release the lock.
  }
  if (proc != 0)
    pid = proc->wait (timeout, status);
  else
    {
      ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
      // Wait for any Process spawned by this Process_Manager.
#if defined (ACE_WIN32)
      HANDLE *handles = 0;

      ACE_NEW_RETURN (handles,
                      HANDLE[this->current_count_],
                      ACE_INVALID_PID);

      for (size_t i = 0;
           i < this->current_count_;
           ++i)
        handles[i] =
          process_table_[i].process_->gethandle ();

      DWORD handle_count = static_cast<DWORD> (this->current_count_);
      DWORD result = ::WaitForMultipleObjects (handle_count,
                                               handles,
                                               FALSE,
                                               timeout == ACE_Time_Value::max_time
                                               ? INFINITE
                                               : timeout.msec ());
      if (result == WAIT_FAILED)
        pid = ACE_INVALID_PID;
      else if (result == WAIT_TIMEOUT)
        pid = 0;
      else
        {
          // Green Hills produces a warning that result >=
          // WAIT_OBJECT_0 is a pointless comparison because
          // WAIT_OBJECT_0 is zero and DWORD is unsigned long, so this
          // test is skipped for Green Hills.  Same for mingw.
# if defined (ghs) || defined (__MINGW32__) || defined (_MSC_VER)
          ACE_ASSERT (result < WAIT_OBJECT_0 + this->current_count_);
# else
          ACE_ASSERT (result >= WAIT_OBJECT_0
                      && result < WAIT_OBJECT_0 + this->current_count_);
# endif

          idx = this->find_proc (handles[result - WAIT_OBJECT_0]);

          if (idx != -1)
            {
              pid = process_table_[idx].process_->getpid ();
              result = ::GetExitCodeProcess (handles[result - WAIT_OBJECT_0],
                                             status);
              if (result == 0)
                {
                  // <GetExitCodeProcess> failed!
                  this->remove_proc (idx);
                  pid = ACE_INVALID_PID;
                }
            }
          else
            {
              // uh oh...handle removed from process_table_, even though
              // we're holding a lock!
              delete [] handles;
              ACE_ERROR_RETURN ((LM_ERROR,
                                 ACE_TEXT ("Process removed")
                                 ACE_TEXT (" -- somebody's ignoring the lock!\n")),
                                -1);
            }
        }

      delete [] handles;
#else /* !defined(ACE_WIN32) */
      if (timeout == ACE_Time_Value::max_time)
        pid = ACE_OS::waitpid (-1, status, 0);
      else if (timeout == ACE_Time_Value::zero)
        pid = ACE_OS::waitpid (-1, status, WNOHANG);
      else
        {
# if defined (ACE_LACKS_UNIX_SIGNALS)
          pid = 0;
          ACE_Time_Value sleeptm (1);    // 1 msec
          if (sleeptm > timeout)         // if sleeptime > waittime
            sleeptm = timeout;
          ACE_Time_Value tmo (timeout);  // Need one we can change
          for (ACE_Countdown_Time time_left (&tmo); tmo > ACE_Time_Value::zero ; time_left.update ())
            {
              pid = ACE_OS::waitpid (-1, status, WNOHANG);
              if (pid > 0 || pid == ACE_INVALID_PID)
                break;          // Got a child or an error - all done

              // pid 0, nothing is ready yet, so wait.
              // Do a (very) short sleep (only this thread sleeps).
              ACE_OS::sleep (sleeptm);
            }
# else
          // Force generation of SIGCHLD, even though we don't want to
          // catch it - just need it to interrupt the sleep below.
          // If this object has a reactor set, assume it was given at
          // open(), and there's already a SIGCHLD action set, so no
          // action is needed here.
          ACE_Sig_Action old_action;
          if (this->reactor () == 0)
            {
              ACE_Sig_Action do_sigchld ((ACE_SignalHandler)sigchld_nop);
              do_sigchld.register_action (SIGCHLD, &old_action);
            }

          ACE_Time_Value tmo (timeout);  // Need one we can change
          for (ACE_Countdown_Time time_left (&tmo); ; time_left.update ())
            {
              pid = ACE_OS::waitpid (-1, status, WNOHANG);
#   if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)
              if (pid > 0 || (pid == ACE_INVALID_PID && errno != EINTR))
#   else
                if (pid > 0 || pid == ACE_INVALID_PID)
#   endif
                  break;          // Got a child or an error - all done

              // pid 0, nothing is ready yet, so wait.
              // Do a sleep (only this thread sleeps) til something
              // happens. This relies on SIGCHLD interrupting the sleep.
              // If SIGCHLD isn't delivered, we'll need to do something
              // with sigaction to force it.
              if (-1 == ACE_OS::sleep (tmo) && errno == EINTR)
                continue;
              // Timed out
              pid = 0;
              break;
            }

          // Restore the previous SIGCHLD action if it was changed.
          if (this->reactor () == 0)
            old_action.register_action (SIGCHLD);
# endif /* !ACE_LACKS_UNIX_SIGNALS */
        }
#endif /* !defined (ACE_WIN32) */
    }

  ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, this->lock_, -1));
  if (pid != ACE_INVALID_PID && pid != 0)
    {
      //we always need to get our id, because we could have been moved in the table meanwhile
      idx = this->find_proc (pid);
      if (idx == -1)
        {
          // oops, reaped an unmanaged process!
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT ("(%P|%t) oops, reaped unmanaged %d\n"),
                      pid));
          return pid;
        }
      else
        proc = process_table_[idx].process_;
      if (proc != 0)
        ACE_ASSERT (pid == proc->getpid ());

      this->notify_proc_handler (idx,
                                 *status);
      this->remove (pid);
    }

  return pid;
}
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[])
{
#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;
}