195
182
posix_spawnattr_t spawnattr;
196
183
posix_spawnattr_init(&spawnattr);
200
fatal_assert(posix_spawnattr_setsigmask(&spawnattr, &set) == 0);
187
// Child should not block signals
188
flags |= POSIX_SPAWN_SETSIGMASK;
193
fatal_assert(posix_spawnattr_setsigmask(&spawnattr, &mask) == 0);
195
#if defined(POSIX_SPAWN_USEVFORK) || defined(__linux__)
196
// Use USEVFORK on linux
197
flags |= POSIX_SPAWN_USEVFORK;
200
flags |= POSIX_SPAWN_SETPGROUP;
201
fatal_assert(posix_spawnattr_setpgroup(&spawnattr, 0) == 0);
203
fatal_assert(posix_spawnattr_setflags(&spawnattr, flags) == 0);
202
205
create_argv(args);
260
spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], NULL);
264
spawn_ret= posix_spawnp(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], NULL);
260
spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], NULL);
268
263
posix_spawn_file_actions_destroy(&file_actions);
279
274
Error << strerror(spawn_ret) << "(" << spawn_ret << ")";
282
return Application::INVALID;
277
return Application::INVALID_POSIX_SPAWN;
283
return Application::INVALID_POSIX_SPAWN;
287
app_thread_st* _app_thread= new app_thread_st(_pid, _status, built_argv[0], _app_exit_state);
289
if ((error= pthread_create(&_thread, NULL, &app_thread, _app_thread)) != 0)
291
Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
292
return Application::FAILURE;
285
296
return Application::SUCCESS;
409
401
return data_was_read;
412
Application::error_t Application::wait(bool nohang)
416
return Application::INVALID;
421
error_t exit_code= FAILURE;
425
if ((waited_pid= waitpid(_pid, &status, nohang ? WNOHANG : 0)) == -1)
430
exit_code= Application::SUCCESS;
437
Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(_pid);
441
else if (waited_pid == 0)
443
exit_code= Application::SUCCESS;
447
if (waited_pid != _pid)
449
throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Pid mismatch, %d != %d", int(waited_pid), int(_pid));
451
exit_code= int_to_error_t(exited_successfully(status));
458
if (exit_code == Application::INVALID)
460
Error << print_argv(built_argv, _argc);
467
404
Application::error_t Application::join()
471
return Application::INVALID;
476
error_t exit_code= FAILURE;
481
waited_pid= waitpid(_pid, &status, 0);
482
} while (waited_pid == -1 and (errno == EINTR or errno == EAGAIN));
484
if (waited_pid == -1)
406
pid_t waited_pid= waitpid(_pid, &_status, 0);
408
if (waited_pid == _pid and WIFEXITED(_status) == false)
411
What we are looking for here is how the exit status happened.
412
- 127 means that posix_spawn() itself had an error.
413
- If WEXITSTATUS is positive we need to see if it is a signal that we sent to kill the process. If not something bad happened in the process itself.
414
- Finally something has happened that we don't currently understand.
416
if (WEXITSTATUS(_status) == 127)
418
_app_exit_state= Application::INVALID_POSIX_SPAWN;
419
std::string error_string("posix_spawn() failed pid:");
421
error_string+= " name:";
422
error_string+= built_argv[0];
423
throw std::logic_error(error_string);
425
else if WIFSIGNALED(_status)
427
// memcached will die with SIGHUP
428
if (WTERMSIG(_status) != SIGTERM and WTERMSIG(_status) != SIGHUP)
489
exit_code= Application::SUCCESS;
496
Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(_pid);
430
_app_exit_state= Application::INVALID_POSIX_SPAWN;
431
std::string error_string(built_argv[0]);
432
error_string+= " was killed by signal ";
433
error_string+= strsignal(WTERMSIG(_status));
434
throw std::runtime_error(error_string);
500
else if (waited_pid == 0)
502
exit_code= Application::SUCCESS;
437
_app_exit_state= Application::SIGTERM_KILLED;
438
Error << "waitpid() application terminated at request"
440
<< " name:" << built_argv[0];
506
if (waited_pid != _pid)
508
throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Pid mismatch, %d != %d", int(waited_pid), int(_pid));
511
exit_code= int_to_error_t(exited_successfully(status));
444
_app_exit_state= Application::UNKNOWN;
445
Error << "Unknown logic state at exit:" << WEXITSTATUS(_status)
447
<< " name:" << built_argv[0];
518
if (exit_code == Application::INVALID)
520
Error << print_argv(built_argv, _argc);
450
else if (waited_pid == _pid and WIFEXITED(_status))
452
_app_exit_state= int_to_error_t(WEXITSTATUS(_status));
454
else if (waited_pid == -1)
456
_app_exit_state= Application::UNKNOWN;
457
Error << "waitpid() returned errno:" << strerror(errno);
461
_app_exit_state= Application::UNKNOWN;
462
throw std::logic_error("waitpid() returned an unknown value");
465
return _app_exit_state;
527
468
void Application::add_long_option(const std::string& name, const std::string& option_value)
605
546
void Application::Pipe::nonblock()
608
if ((ret= fcntl(_pipe_fd[READ], F_GETFL, 0)) == -1)
550
flags= fcntl(_pipe_fd[READ], F_GETFL, 0);
551
} while (flags == -1 and (errno == EINTR or errno == EAGAIN));
610
555
Error << "fcntl(F_GETFL) " << strerror(errno);
611
556
throw strerror(errno);
614
if ((ret= fcntl(_pipe_fd[READ], F_SETFL, ret | O_NONBLOCK)) == -1)
562
rval= fcntl(_pipe_fd[READ], F_SETFL, flags | O_NONBLOCK);
563
} while (rval == -1 and (errno == EINTR or errno == EAGAIN));
616
567
Error << "fcntl(F_SETFL) " << strerror(errno);
617
568
throw strerror(errno);
588
#if defined(HAVE_PIPE2) && HAVE_PIPE2
644
596
void Application::Pipe::cloexec()
647
if ((ret= fcntl(_pipe_fd[WRITE], F_GETFD, 0)) == -1)
649
Error << "fcntl(F_GETFD) " << strerror(errno);
650
throw strerror(errno);
653
if ((ret= fcntl(_pipe_fd[WRITE], F_SETFD, ret | FD_CLOEXEC)) == -1)
655
Error << "fcntl(F_SETFD) " << strerror(errno);
656
throw strerror(errno);
598
//if (SOCK_CLOEXEC == 0)
605
flags= fcntl(_pipe_fd[WRITE], F_GETFD, 0);
606
} while (flags == -1 and (errno == EINTR or errno == EAGAIN));
610
Error << "fcntl(F_GETFD) " << strerror(errno);
611
throw strerror(errno);
617
rval= fcntl(_pipe_fd[WRITE], F_SETFD, flags | FD_CLOEXEC);
618
} while (rval == -1 && (errno == EINTR or errno == EAGAIN));
622
Error << "fcntl(F_SETFD) " << strerror(errno);
623
throw strerror(errno);