예제 #1
0
TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGDEF) {
  // Ignore SIGALRM and SIGCONT in the parent...
  ASSERT_NE(SIG_ERR, signal(SIGALRM, SIG_IGN));
  ASSERT_NE(SIG_ERR, signal(SIGCONT, SIG_IGN));

  posix_spawnattr_t sa;
  ASSERT_EQ(0, posix_spawnattr_init(&sa));

  // Ask for SIGALRM to be defaulted in the child...
  sigset_t just_SIGALRM;
  sigemptyset(&just_SIGALRM);
  sigaddset(&just_SIGALRM, SIGALRM);

  ASSERT_EQ(0, posix_spawnattr_setsigdefault(&sa, &just_SIGALRM));
  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGDEF));

  // Check that's what happens...
  ProcStatus ps = {};
  GetChildStatus(&sa, &ps);

  // TIMER_SIGNAL should be blocked.
  uint64_t expected_blocked = 0;
  SignalSetAdd(&expected_blocked, __SIGRTMIN + 0);
  EXPECT_EQ(expected_blocked, ps.sigblk);

  uint64_t expected_ignored = 0;
  SignalSetAdd(&expected_ignored, SIGCONT);
  EXPECT_EQ(expected_ignored, ps.sigign);

  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
예제 #2
0
static void spawn_win32(void) {
  char module_name[WATCHMAN_NAME_MAX];
  GetModuleFileName(NULL, module_name, sizeof(module_name));
  char *argv[MAX_DAEMON_ARGS] = {
    module_name,
    "--foreground",
    NULL
  };
  posix_spawn_file_actions_t actions;
  posix_spawnattr_t attr;
  pid_t pid;
  int i;

  for (i = 0; daemon_argv[i]; i++) {
    append_argv(argv, daemon_argv[i]);
  }

  posix_spawnattr_init(&attr);
  posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP);
  posix_spawn_file_actions_init(&actions);
  posix_spawn_file_actions_addopen(&actions,
      STDIN_FILENO, "/dev/null", O_RDONLY, 0);
  posix_spawn_file_actions_addopen(&actions,
      STDOUT_FILENO, log_name, O_WRONLY|O_CREAT|O_APPEND, 0600);
  posix_spawn_file_actions_adddup2(&actions,
      STDOUT_FILENO, STDERR_FILENO);
  posix_spawnp(&pid, argv[0], &actions, &attr, argv, environ);
  posix_spawnattr_destroy(&attr);
  posix_spawn_file_actions_destroy(&actions);
}
예제 #3
0
void target_proc(struct execute_context *ctx)
{
    int ret;

    char **args = ctx->passing_args;
    short ps_flags = 0;
    pid_t pid;
    posix_spawn_file_actions_t actions;
    posix_spawnattr_t attrs;

    if (args == NULL) {
        return;
    }

    RESET_ERROR;
    posix_spawn_file_actions_init(&actions);
    posix_spawnattr_init(&attrs);

#ifndef _POSIX_SPAWN_DISABLE_ASLR
#   define _POSIX_SPAWN_DISABLE_ASLR 0x0100
#endif
    ps_flags |= POSIX_SPAWN_SETEXEC;
    ps_flags |= _POSIX_SPAWN_DISABLE_ASLR;
    ret = posix_spawnattr_setflags(&attrs, ps_flags);
    if (ret != 0) {
        fprintf(stderr, "cannot set posix_spawn flags\n");
        return;
    }

    /* attached */
    ret = ptrace(PT_TRACE_ME, 0, 0, 0);
    posix_spawn(&pid, args[0], &actions, &attrs, args, NULL);
    fprintf(stderr, "Failed\n");
    exit(1);
}
예제 #4
0
TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGMASK) {
  // Block SIGBUS in the parent...
  sigset_t just_SIGBUS;
  sigemptyset(&just_SIGBUS);
  sigaddset(&just_SIGBUS, SIGBUS);
  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGBUS, nullptr));

  posix_spawnattr_t sa;
  ASSERT_EQ(0, posix_spawnattr_init(&sa));

  // Ask for only SIGALRM to be blocked in the child...
  sigset_t just_SIGALRM;
  sigemptyset(&just_SIGALRM);
  sigaddset(&just_SIGALRM, SIGALRM);
  ASSERT_EQ(0, posix_spawnattr_setsigmask(&sa, &just_SIGALRM));
  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGMASK));

  // Check that's what happens...
  ProcStatus ps = {};
  GetChildStatus(&sa, &ps);

  // TIMER_SIGNAL should also be blocked.
  uint64_t expected_blocked = 0;
  SignalSetAdd(&expected_blocked, SIGALRM);
  SignalSetAdd(&expected_blocked, __SIGRTMIN + 0);
  EXPECT_EQ(expected_blocked, ps.sigblk);

  EXPECT_EQ(static_cast<uint64_t>(0), ps.sigign);

  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
예제 #5
0
pid_t
rb_spawn_process(const char *path, const char **argv)
{
    pid_t pid;
    const void *arghack = argv;
    char **myenviron;
    int error;
    posix_spawnattr_t spattr;
    posix_spawnattr_init(&spattr);
#ifdef POSIX_SPAWN_USEVFORK
    posix_spawnattr_setflags(&spattr, POSIX_SPAWN_USEVFORK);
#endif
#ifdef __APPLE__
    myenviron = *_NSGetEnviron(); /* apple needs to go f**k themselves for this */
#else
    myenviron = environ;
#endif
    error = posix_spawn(&pid, path, NULL, &spattr, arghack, myenviron);
    posix_spawnattr_destroy(&spattr);
    if (error != 0) {
        errno = error;
        pid = -1;
    }
    return pid;
}
예제 #6
0
파일: posix.c 프로젝트: gcr/lua-spawn
static int l_posix_spawnattr_setflags(lua_State *L) {
	int r;
	posix_spawnattr_t *attr = luaL_checkudata(L, 1, "posix_spawnattr_t");
	short int flags = 0;
	luaL_checktype(L, 2, LUA_TTABLE);
	lua_getfield(L, 2, "resetids");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_RESETIDS;
	lua_getfield(L, 2, "setpgroup");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_SETPGROUP;
	lua_getfield(L, 2, "setsigdef");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_SETSIGDEF;
	lua_getfield(L, 2, "setsigmask");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_SETSIGMASK;
	lua_getfield(L, 2, "setschedparam");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_SETSCHEDPARAM;
	lua_getfield(L, 2, "setscheduler");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_SETSCHEDULER;
	lua_pop(L, 6);
#ifdef POSIX_SPAWN_USEVFORK
	lua_getfield(L, 2, "usevfork");
	if (lua_toboolean(L, -1)) flags |= POSIX_SPAWN_USEVFORK;
	lua_pop(L, 1);
#endif
	if (0 != (r = posix_spawnattr_setflags(attr, flags))) {
		lua_pushnil(L);
		lua_pushstring(L, strerror(r));
		lua_pushinteger(L, r);
		return 3;
	}
	lua_pushboolean(L, 1);
	return 1;
}
예제 #7
0
파일: xdg.c 프로젝트: 0xheart0/vlc
static int Open (vlc_object_t *obj)
{
    vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
    vlc_inhibit_sys_t *p_sys = malloc (sizeof (*p_sys));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    posix_spawnattr_init (&p_sys->attr);
    /* Reset signal handlers to default and clear mask in the child process */
    {
        sigset_t set;

        sigemptyset (&set);
        posix_spawnattr_setsigmask (&p_sys->attr, &set);
        sigaddset (&set, SIGPIPE);
        posix_spawnattr_setsigdefault (&p_sys->attr, &set);
        posix_spawnattr_setflags (&p_sys->attr, POSIX_SPAWN_SETSIGDEF
                                              | POSIX_SPAWN_SETSIGMASK);
    }

    ih->p_sys = p_sys;
    if (vlc_timer_create (&p_sys->timer, Timer, ih))
    {
        posix_spawnattr_destroy (&p_sys->attr);
        free (p_sys);
        return VLC_ENOMEM;
    }

    ih->inhibit = Inhibit;
    return VLC_SUCCESS;
}
예제 #8
0
파일: noaslr.c 프로젝트: CarterTsai/clasp
int main(int argc, char **argv)
{
  extern char **environ;
  pid_t pid;
  posix_spawnattr_t attr;
  int res, status = 1;
  char *default_argv[] = {"/bin/sh", NULL};

  if (argc >= 2)
    ++ argv;
  else
    argv = default_argv;

  res = posix_spawnattr_init(&attr);
  if (res != 0)
    return res;

  res = posix_spawnattr_setflags(&attr, _POSIX_SPAWN_DISABLE_ASLR);
  if (res != 0)
    return res;

  res = posix_spawn(&pid, argv[0], NULL, &attr, argv, environ);
  if (res != 0)
    return res;

  if (waitpid(pid, &status, 0) == -1)
    return 1;

  if (!WIFEXITED(status))
    return 1;

  return WEXITSTATUS(status);
}
예제 #9
0
파일: Launch.c 프로젝트: mountainstorm/Flow
/*
 * Static function implementations
 */
pid_t Launch_posixSpawnSuspended(cpu_type_t cpuType, const char *path, char** argv) {
	pid_t retVal = -1;
	
	if (path == NULL || argv == NULL) {
		Log_invalidArgument("path: %p, argv: %p", path, argv);
		
	} else {
		posix_spawnattr_t attr = 0;
		int ret = posix_spawnattr_init(&attr);
		if (ret != 0) {
			Log_errorPosix(ret, "posix_spawnattr_init");
			
		} else {
			sigset_t no_signals = 0;
			sigset_t all_signals = 0;
			sigemptyset(&no_signals);
			sigfillset(&all_signals);
			posix_spawnattr_setsigmask(&attr, &no_signals);
			posix_spawnattr_setsigdefault(&attr, &all_signals);

			if (cpuType != CPU_TYPE_ANY) {
				size_t ocount = 0;
				// if specified choose the arch from the fat binary to run
				ret = posix_spawnattr_setbinpref_np(&attr, 1, &cpuType, &ocount);
				if (ret != 0) {
					Log_errorPosix(ret, "posix_spawnattr_setbinpref_np");
				}
			}
			
			if (ret == 0) {
				ret = posix_spawnattr_setflags(&attr, 
											     POSIX_SPAWN_START_SUSPENDED 
											   | _POSIX_SPAWN_DISABLE_ASLR 
											   | POSIX_SPAWN_SETSIGDEF 
											   | POSIX_SPAWN_SETSIGMASK);
				if (ret != 0) {
					Log_errorPosix(ret, "posix_spawnattr_setflags");
					
				} else {
					pid_t pid = -1;
					ret = posix_spawnp(&pid, 
									   path, 
									   NULL, 
									   &attr, 
									   (char * const*)argv, 
									   (char * const*)NULL);
					if (ret != 0) {
						Log_errorPosix(ret, "posix_spawnp");
						
					} else {
						retVal = pid;
					}
				}
			}
			posix_spawnattr_destroy(&attr);
		}
	}
	return retVal;
}
예제 #10
0
파일: pythonw.c 프로젝트: 0xcc/python-read
static void
setup_spawnattr(posix_spawnattr_t* spawnattr)
{
    size_t ocount;
    size_t count;
    cpu_type_t cpu_types[1];
    short flags = 0;
#ifdef __LP64__
    int   ch;
#endif

    if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
        err(2, "posix_spawnattr_int");
        /* NOTREACHTED */
    }

    count = 1;

    /* Run the real python executable using the same architecture as this
     * executable, this allows users to control the architecture using
     * "arch -ppc python"
     */

#if defined(__ppc64__)
    cpu_types[0] = CPU_TYPE_POWERPC64;

#elif defined(__x86_64__)
    cpu_types[0] = CPU_TYPE_X86_64;

#elif defined(__ppc__)
    cpu_types[0] = CPU_TYPE_POWERPC;
#elif defined(__i386__)
    cpu_types[0] = CPU_TYPE_X86;
#else
#       error "Unknown CPU"
#endif

    if (posix_spawnattr_setbinpref_np(spawnattr, count,
                            cpu_types, &ocount) == -1) {
        err(1, "posix_spawnattr_setbinpref");
        /* NOTREACHTED */
    }
    if (count != ocount) {
        fprintf(stderr, "posix_spawnattr_setbinpref failed to copy\n");
        exit(1);
        /* NOTREACHTED */
    }


    /*
     * Set flag that causes posix_spawn to behave like execv
     */
    flags |= POSIX_SPAWN_SETEXEC;
    if ((errno = posix_spawnattr_setflags(spawnattr, flags)) != 0) {
        err(1, "posix_spawnattr_setflags");
        /* NOTREACHTED */
    }
}
예제 #11
0
TEST(spawn, posix_spawnattr_setflags_posix_spawnattr_getflags) {
  posix_spawnattr_t sa;
  ASSERT_EQ(0, posix_spawnattr_init(&sa));

  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_RESETIDS));
  short flags;
  ASSERT_EQ(0, posix_spawnattr_getflags(&sa, &flags));
  ASSERT_EQ(POSIX_SPAWN_RESETIDS, flags);

  constexpr short all_flags = POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF |
                              POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSCHEDPARAM |
                              POSIX_SPAWN_SETSCHEDULER | POSIX_SPAWN_USEVFORK | POSIX_SPAWN_SETSID;
  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, all_flags));
  ASSERT_EQ(0, posix_spawnattr_getflags(&sa, &flags));
  ASSERT_EQ(all_flags, flags);

  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
예제 #12
0
static void
do_test_setsid (bool test_setsid)
{
  pid_t sid, child_sid;
  int res;

  /* Current session ID.  */
  sid = getsid(0);
  if (sid == (pid_t) -1)
    FAIL_EXIT1 ("getsid (0): %m");

  posix_spawnattr_t attrp;
  /* posix_spawnattr_init should not fail (it basically memset the
     attribute).  */
  posix_spawnattr_init (&attrp);
  if (test_setsid)
    {
      res = posix_spawnattr_setflags (&attrp, POSIX_SPAWN_SETSID);
      if (res != 0)
	{
	  errno = res;
	  FAIL_EXIT1 ("posix_spawnattr_setflags: %m");
	}
    }

  /* Program to run.  */
  char *args[2] = { (char *) "true", NULL };
  pid_t child;

  res = posix_spawnp (&child, "true", NULL, &attrp, args, environ);
  /* posix_spawnattr_destroy is noop.  */
  posix_spawnattr_destroy (&attrp);

  if (res != 0)
    {
      errno = res;
      FAIL_EXIT1 ("posix_spawnp: %m");
    }

  /* Child should have a different session ID than parent.  */
  child_sid = getsid (child);

  if (child_sid == (pid_t) -1)
    FAIL_EXIT1 ("getsid (%i): %m", child);

  if (test_setsid)
    {
      if (child_sid == sid)
	FAIL_EXIT1 ("child session ID matched parent one");
    }
  else
    {
      if (child_sid != sid)
	FAIL_EXIT1 ("child session ID did not match parent one");
    }
}
예제 #13
0
파일: spawn.c 프로젝트: o-lim/lua-ex
struct spawn_params *spawn_param_init(lua_State *L)
{
  struct spawn_params *p = lua_newuserdata(L, sizeof *p);
  p->L = L;
  p->command = 0;
  p->argv = p->envp = 0;
  posix_spawn_file_actions_init(&p->redirect);
  posix_spawnattr_init(&p->attr);
  posix_spawnattr_setflags(&p->attr, POSIX_SPAWN_USEVFORK);
  return p;
}
예제 #14
0
int main (void)
{
  pid_t pid ;
  posix_spawn_file_actions_t actions ;
  posix_spawnattr_t attr ;
  char *const argv[2] = { "/bin/true", 0 } ;
  char *const envp[1] = { 0 } ;
  posix_spawnattr_setflags(&attr, 0) ;
  posix_spawn_file_actions_init(&actions) ;
  return posix_spawn(&pid, argv[0], 0, 0, argv, envp) ;
}
예제 #15
0
static pid_t start_program(char **command, sigset_t *mask)
{
	char **arg, *s;
	pid_t pid;

#ifdef HAVE_POSIX_SPAWN
	posix_spawnattr_t attr;

	if (posix_spawnattr_init(&attr)) {
		pr_err("failed to init spawn attributes: %m");
		return 0;
	}

	if (posix_spawnattr_setsigmask(&attr, mask) ||
	    posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK) ||
	    posix_spawnp(&pid, command[0], NULL, &attr, command, environ)) {
		pr_err("failed to spawn %s: %m", command[0]);
		posix_spawnattr_destroy(&attr);
		return 0;
	}

	posix_spawnattr_destroy(&attr);
#else
	pid = fork();

	if (pid < 0) {
		pr_err("fork() failed: %m");
		return 0;
	}

	if (!pid) {
		/* restore the signal mask */
		if (sigprocmask(SIG_SETMASK, mask, NULL) < 0) {
			pr_err("sigprocmask() failed: %m");
			exit(100);
		}

		execvp(command[0], (char **)command);

		pr_err("failed to execute %s: %m", command[0]);

		exit(101);
	}
#endif

	for (s = xstrdup(""), arg = command; *arg; arg++)
		string_appendf(&s, "%s ", *arg);

	pr_info("process %d started: %s", pid, s);

	free(s);

	return pid;
}
예제 #16
0
TEST(spawn, posix_spawn_POSIX_SPAWN_SETPGROUP_clear) {
  pid_t parent_pgrp = getpgrp();

  posix_spawnattr_t sa;
  ASSERT_EQ(0, posix_spawnattr_init(&sa));
  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, 0));

  ProcStat ps = {};
  GetChildStat(&sa, &ps);
  ASSERT_EQ(parent_pgrp, ps.pgrp);
  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
예제 #17
0
파일: main.c 프로젝트: wzw19890321/dyld
static struct task_and_pid launchTest(const char* testProgPath, bool launchOtherArch, bool launchSuspended)
{
    posix_spawnattr_t attr = 0;
    if ( posix_spawnattr_init(&attr) != 0 ) {
        printf("[FAIL] dyld_process_info posix_spawnattr_init()\n");
        exit(0);
    }
    if ( launchSuspended ) {
        if ( posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED) != 0 ) {
            printf("[FAIL] dyld_process_info POSIX_SPAWN_START_SUSPENDED\n");
            exit(0);
        }
    }
    if ( launchOtherArch ) {
        size_t copied;
        if ( posix_spawnattr_setbinpref_np(&attr, 1, otherArch, &copied) != 0 ) {
           printf("[FAIL] dyld_process_info posix_spawnattr_setbinpref_np()\n");
            exit(0);
        }
    }

    struct task_and_pid child = {0, 0};
    const char* argv[] = { testProgPath, NULL };
    int psResult = posix_spawn(&child.pid, testProgPath, NULL, &attr, (char**)argv, environ);
    if ( psResult != 0 ) {
        printf("[FAIL] dyld_process_info posix_spawn(%s) failed, err=%d\n", testProgPath, psResult);
        exit(0);
    }
    if (posix_spawnattr_destroy(&attr) != 0) {
        printf("[FAIL] dyld_process_info posix_spawnattr_destroy()\n");
        exit(0);
    }

    if ( task_for_pid(mach_task_self(), child.pid, &child.task) != KERN_SUCCESS ) {
        printf("[FAIL] dyld_process_info task_for_pid()\n");
        kill(child.pid, SIGKILL);
        exit(0);
    }

#if __x86_64__
    //printf("child pid=%d task=%d (%s, %s)\n", child.pid, child.task, launchOtherArch ? "i386" : "x86_64",  launchSuspended ? "suspended" : "active");
#endif

    // wait until process is up and has suspended itself
    struct task_basic_info info;
    do {
        unsigned count = TASK_BASIC_INFO_COUNT;
        kern_return_t kr = task_info(child.task, TASK_BASIC_INFO, (task_info_t)&info, &count);
        sleep(1);
    } while ( info.suspend_count == 0 );

    return child;
}
예제 #18
0
TEST(spawn, posix_spawn_POSIX_SPAWN_SETSID_set) {
  pid_t parent_sid = getsid(0);

  posix_spawnattr_t sa;
  ASSERT_EQ(0, posix_spawnattr_init(&sa));
  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSID));

  ProcStat ps = {};
  GetChildStat(&sa, &ps);
  ASSERT_NE(parent_sid, ps.sid);
  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
예제 #19
0
TEST(spawn, signal_stress) {
  // Ensure that posix_spawn doesn't restore the caller's signal mask in the
  // child without first defaulting any caught signals (http://b/68707996).
  static pid_t parent = getpid();

  setpgid(0, 0);
  signal(SIGRTMIN, SIG_IGN);

  pid_t pid = fork();
  ASSERT_NE(-1, pid);

  if (pid == 0) {
    for (size_t i = 0; i < 1024; ++i) {
      kill(0, SIGRTMIN);
      usleep(10);
    }
    _exit(99);
  }

  // We test both with and without attributes, because they used to be
  // different codepaths. We also test with an empty `sigdefault` set.
  posix_spawnattr_t attr1;
  posix_spawnattr_init(&attr1);

  sigset_t empty_mask = {};
  posix_spawnattr_t attr2;
  posix_spawnattr_init(&attr2);
  posix_spawnattr_setflags(&attr2, POSIX_SPAWN_SETSIGDEF);
  posix_spawnattr_setsigdefault(&attr2, &empty_mask);

  posix_spawnattr_t* attrs[] = { nullptr, &attr1, &attr2 };

  // We use a real-time signal because that's a tricky case for LP32
  // because our sigset_t was too small.
  ScopedSignalHandler ssh(SIGRTMIN, [](int) { ASSERT_EQ(getpid(), parent); });

  const size_t pid_count = 128;
  pid_t spawned_pids[pid_count];

  ExecTestHelper eth;
  eth.SetArgs({"true", nullptr});
  for (size_t i = 0; i < pid_count; ++i) {
    pid_t spawned_pid;
    ASSERT_EQ(0, posix_spawn(&spawned_pid, "true", nullptr, attrs[i % 3], eth.GetArgs(), nullptr));
    spawned_pids[i] = spawned_pid;
  }

  for (pid_t spawned_pid : spawned_pids) {
    ASSERT_EQ(spawned_pid, TEMP_FAILURE_RETRY(waitpid(spawned_pid, nullptr, 0)));
  }

  AssertChildExited(pid, 99);
}
예제 #20
0
void
test_proc(pid_t bad_pid)
{
	dispatch_source_t proc_s[PID_CNT], proc;
	int res;
	pid_t pid, monitor_pid;

	event_cnt = 0;
	// Creates a process and register multiple observers.  Send a signal,
	// exit the process, etc., and verify all observers were notified.

	posix_spawnattr_t attr;
	res = posix_spawnattr_init(&attr);
	assert(res == 0);
#if HAVE_DECL_POSIX_SPAWN_START_SUSPENDED
	res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
	assert(res == 0);
#endif

	char* args[] = {
		"/bin/sleep", "2", NULL
	};

	res = posix_spawnp(&pid, args[0], NULL, &attr, args, NULL);
	if (res < 0) {
		perror(args[0]);
		exit(127);
	}

	res = posix_spawnattr_destroy(&attr);
	assert(res == 0);

	dispatch_group_t group = dispatch_group_create();

	assert(pid > 0);
	monitor_pid = bad_pid ? bad_pid : pid; // rdar://problem/8090801

	int i;
	for (i = 0; i < PID_CNT; ++i) {
		dispatch_group_enter(group);
		proc = proc_s[i] = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC,
				monitor_pid, DISPATCH_PROC_EXIT, dispatch_get_global_queue(0, 0));
		test_ptr_notnull("dispatch_source_proc_create", proc);
		dispatch_source_set_event_handler(proc, ^{
			long flags = dispatch_source_get_data(proc);
			test_long("DISPATCH_PROC_EXIT", flags, DISPATCH_PROC_EXIT);
			event_cnt++;
			dispatch_source_cancel(proc);
		});
		dispatch_source_set_cancel_handler(proc, ^{
			dispatch_group_leave(group);
		});
예제 #21
0
void ChildProcess::Options::setFlags(short flags) {
  short currentFlags;
  auto err = posix_spawnattr_getflags(&inner_->attr, &currentFlags);
  if (err) {
    throw std::system_error(
        err, std::generic_category(), "posix_spawnattr_getflags");
  }
  err = posix_spawnattr_setflags(&inner_->attr, currentFlags | flags);
  if (err) {
    throw std::system_error(
        err, std::generic_category(), "posix_spawnattr_setflags");
  }
}
예제 #22
0
pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to)
{
  posix_spawn_file_actions_t actions ;
  posix_spawnattr_t attr ;
  int e ;
  pid_t pid ;
  int haspath = !!env_get("PATH") ;
  if (coe(p[!(to & 1)]) < 0) { e = errno ; goto err ; }
  e = posix_spawnattr_init(&attr) ;
  if (e) goto err ;
  {
    sigset_t set ;
    sigemptyset(&set) ;
    e = posix_spawnattr_setsigmask(&attr, &set) ;
    if (e) goto errattr ;
    e = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK) ;
    if (e) goto errattr ;
  }
  e = posix_spawn_file_actions_init(&actions) ;
  if (e) goto errattr ;
  e = posix_spawn_file_actions_adddup2(&actions, p[to & 1], to & 1) ;
  if (e) goto erractions ;
  e = posix_spawn_file_actions_addclose(&actions, p[to & 1]) ;
  if (e) goto erractions ;
  if (to & 2)
  {
    e = posix_spawn_file_actions_adddup2(&actions, to & 1, !(to & 1)) ;
    if (e) goto erractions ;
  }
  if (!haspath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) < 0)) { e = errno ; goto erractions ; }
  e = posix_spawnp(&pid, prog, &actions, &attr, (char *const *)argv, (char *const *)envp) ;
  if (!haspath) unsetenv("PATH") ;
  posix_spawn_file_actions_destroy(&actions) ;
  posix_spawnattr_destroy(&attr) ;
  fd_close(p[to & 1]) ;
  if (e) goto errp ;
  return pid ;

 erractions:
  posix_spawn_file_actions_destroy(&actions) ;
 errattr:
  posix_spawnattr_destroy(&attr) ;
 err:
  fd_close(p[to & 1]) ;
 errp:
  fd_close(p[!(to & 1)]) ;
  errno = e ;
  return 0 ;
}
예제 #23
0
TEST(spawn, posix_spawn_POSIX_SPAWN_SETPGROUP_set) {
  pid_t parent_pgrp = getpgrp();

  posix_spawnattr_t sa;
  ASSERT_EQ(0, posix_spawnattr_init(&sa));
  ASSERT_EQ(0, posix_spawnattr_setpgroup(&sa, 0));
  ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETPGROUP));

  ProcStat ps = {};
  GetChildStat(&sa, &ps);
  ASSERT_NE(parent_pgrp, ps.pgrp);
  // Setting pgid 0 means "the same as the caller's pid".
  ASSERT_EQ(ps.pid, ps.pgrp);
  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
예제 #24
0
파일: pspawn3.c 프로젝트: h9379203/linet
int main()
{
	int		ret_err = 0;
	pid_t	pid_child;
	char	buf_err[64];
	char	*argv_child[] = {
		"forkexec_child", NULL
	};
	printf("Parent[%d]: Start\n", getpid());

	posix_spawnattr_t	posix_attr;
	if ((ret_err = posix_spawnattr_init(&posix_attr)) != 0) {
		strerror_r(ret_err, buf_err, sizeof(buf_err));
		fprintf(stderr, "Fail: attr_init: %s\n", buf_err);
		exit(EXIT_FAILURE);
	}
	short posix_flags = POSIX_SPAWN_SETPGROUP;
	if ((ret_err = posix_spawnattr_setflags(&posix_attr, posix_flags)) != 0) {
		strerror_r(ret_err, buf_err, sizeof(buf_err));
		fprintf(stderr, "Fail: attr_setflags: %s\n", buf_err);
		exit(EXIT_FAILURE);
	}

	// set pgid
	pid_t	pid_pgid = 0; /* child process shall become process group reader */
	if ((ret_err = posix_spawnattr_setpgroup(&posix_attr, pid_pgid)) != 0) {
		strerror_r(ret_err, buf_err, sizeof(buf_err));
		fprintf(stderr, "Fail: attr_setpgroup: %s\n", buf_err);
		exit(EXIT_FAILURE);
	}

	ret_err = posix_spawn( &pid_child,
			argv_child[0],
			NULL,
			&posix_attr,		/* attribute */
			argv_child,
			NULL);
	if ((ret_err = posix_spawnattr_destroy(&posix_attr)) != 0) {
		strerror_r(ret_err, buf_err, sizeof(buf_err));
		fprintf(stderr, "Fail: attr_destroy: %s\n", buf_err);
		exit(EXIT_FAILURE);
	}
	printf("Parent[%d]: Wait for child(%d)\n", getpid(), (int)pid_child);
	(void)wait(NULL);	/* wait for child */
	printf("Parent[%d]: Exit\n", getpid());
	return 0;
}
예제 #25
0
int
main(int argc, char *argv[])
{
    dispatch_source_t tmp_ds;
    int res;
    pid_t pid;

    if (argc < 2) {
        fprintf(stderr, "usage: harness [...]\n");
        exit(1);
    }

    posix_spawnattr_t attr;
    res = posix_spawnattr_init(&attr);
    assert(res == 0);
    res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
    assert(res == 0);

    int i;
    char** newargv = calloc(argc, sizeof(void*));
    for (i = 1; i < argc; ++i) {
        newargv[i-1] = argv[i];
    }
    newargv[i-1] = NULL;

    res = posix_spawnp(&pid, newargv[0], NULL, &attr, newargv, environ);
    if (res) {
        errno = res;
        perror(newargv[0]);
        exit(EXIT_FAILURE);
    }
    //fprintf(stderr, "pid = %d\n", pid);
    assert(pid > 0);

    dispatch_queue_t main_q = dispatch_get_main_queue();

    tmp_ds = dispatch_source_proc_create(pid, DISPATCH_PROC_EXIT, NULL, main_q,
    ^(dispatch_event_t ev __attribute__((unused))) {
        int status;
        int res2 = waitpid(pid, &status, 0);
        assert(res2 != -1);
        //int passed = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
        test_long("Process exited", WEXITSTATUS(status) | WTERMSIG(status), 0);
        exit(0);
    });
예제 #26
0
static int l_posix_spawnattr_setflags(lua_State *L) {
	int r;
	size_t i;
	posix_spawnattr_t *attr = luaL_checkudata(L, 1, "posix_spawnattr_t");
	short int flags = 0;
	luaL_checktype(L, 2, LUA_TTABLE);
	for (i=0; i<N_SUPPORTED_FLAGS; i++) {
		lua_getfield(L, 2, supported_flags[i].flagname);
		if (lua_toboolean(L, -1)) flags |= supported_flags[i].value;
		lua_pop(L, 1);
	}
	if (0 != (r = posix_spawnattr_setflags(attr, flags))) {
		lua_pushnil(L);
		lua_pushstring(L, strerror(r));
		lua_pushinteger(L, r);
		return 3;
	}
	lua_pushboolean(L, 1);
	return 1;
}
예제 #27
0
pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
                                                      char **argv,
                                                      char **envp,
                                                      pid_t pgid)
{
   int err = 0;
   pid_t pid;
   posix_spawnattr_t attr;
   int attr_init_done = 0;

   err = posix_spawnattr_init(&attr);
   if (err != 0)
      goto out;
   attr_init_done = 1;

   err = posix_spawnattr_init(&attr);
   if (err != 0)
      goto out;

   if (pgid != 0) {
      if (pgid <= 1)
         pgid = 0;
      err = posix_spawnattr_setpgroup(&attr, pgid);
      if (err != 0)
         goto out;
      err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP);
      if (err != 0)
         goto out;
   }

   err = posix_spawn(&pid, command, NULL, &attr, argv, envp ? envp : environ);

out:
   if (attr_init_done)
      posix_spawnattr_destroy(&attr);
   if (err != 0) {
      errno = err;
      return -1;
   }
   return pid;
}
예제 #28
0
static void tc_libc_spawn_posix_spawnattr_setgetflags(void)
{
	int ret_chk = ERROR;
	pid_t pid;
	posix_spawnattr_t st_attr;
	short int flags;

	ret_chk = posix_spawnattr_init(&st_attr);
	TC_ASSERT_EQ("posix_spawnattr_init", ret_chk, OK);

	ret_chk = posix_spawnattr_setflags(&st_attr, POSIX_SPAWN_SETSCHEDPARAM);
	TC_ASSERT_EQ("posix_spawnattr_setflags", ret_chk, OK);

	ret_chk = task_spawn(&pid, "spawn_flag", function_name_spawn, NULL, &st_attr, (char *const *)NULL, (char *const *)NULL);
	sleep(SEC_3);
	TC_ASSERT_EQ("task_spawn", ret_chk, OK);

	ret_chk = posix_spawnattr_getflags(&st_attr, &flags);
	TC_ASSERT_EQ("posix_spawnattr_getflags", ret_chk, OK);
	TC_ASSERT_EQ("posix_spawnattr_getflags", flags, POSIX_SPAWN_SETSCHEDPARAM);

	TC_SUCCESS_RESULT();
}
예제 #29
0
pid_t
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
{
	int			err;
	pid_t			pid;
	posix_spawnattr_t	attr;

	if (err = posix_spawnattr_init(&attr))
		goto nope;
	if (pgid)
	{
		if (pgid <= 1)
			pgid = 0;
		if (err = posix_spawnattr_setpgroup(&attr, pgid))
			goto bad;
		if (err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
			goto bad;
	}
	if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ))
		goto bad;
	posix_spawnattr_destroy(&attr);
#if _lib_posix_spawn < 2
	if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) == 127)
	{
		while (waitpid(pid, NiL, 0) == -1 && errno == EINTR);
		if (!access(path, X_OK))
			errno = ENOEXEC;
		pid = -1;
	}
#endif
	return pid;
 bad:
	posix_spawnattr_destroy(&attr);
 nope:
	errno = err;
	return -1;
}
예제 #30
0
bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_file_actions_t *actions, job_t *j, process_t *p, const io_chain_t &io_chain)
{
    /* Initialize the output */
    if (posix_spawnattr_init(attr) != 0)
    {
        return false;
    }

    if (posix_spawn_file_actions_init(actions) != 0)
    {
        posix_spawnattr_destroy(attr);
        return false;
    }

    bool should_set_parent_group_id = false;
    int desired_parent_group_id = 0;
    if (job_get_flag(j, JOB_CONTROL))
    {
        should_set_parent_group_id = true;

        // PCA: I'm quite fuzzy on process groups,
        // but I believe that the default value of 0
        // means that the process becomes its own
        // group leader, which is what set_child_group did
        // in this case. So we want this to be 0 if j->pgid is 0.
        desired_parent_group_id = j->pgid;
    }

    /* Set the handling for job control signals back to the default.  */
    bool reset_signal_handlers = true;

    /* Remove all signal blocks */
    bool reset_sigmask = true;

    /* Set our flags */
    short flags = 0;
    if (reset_signal_handlers)
        flags |= POSIX_SPAWN_SETSIGDEF;
    if (reset_sigmask)
        flags |= POSIX_SPAWN_SETSIGMASK;
    if (should_set_parent_group_id)
        flags |= POSIX_SPAWN_SETPGROUP;

    int err = 0;
    if (! err)
        err = posix_spawnattr_setflags(attr, flags);

    if (! err && should_set_parent_group_id)
        err = posix_spawnattr_setpgroup(attr, desired_parent_group_id);

    /* Everybody gets default handlers */
    if (! err && reset_signal_handlers)
    {
        sigset_t sigdefault;
        get_signals_with_handlers(&sigdefault);
        err = posix_spawnattr_setsigdefault(attr, &sigdefault);
    }

    /* No signals blocked */
    sigset_t sigmask;
    sigemptyset(&sigmask);
    if (! err && reset_sigmask)
        err = posix_spawnattr_setsigmask(attr, &sigmask);
    
    for (size_t idx = 0; idx < io_chain.size(); idx++)
    {
        const shared_ptr<const io_data_t> io = io_chain.at(idx);

        if (io->io_mode == IO_FD)
        {
            CAST_INIT(const io_fd_t *, io_fd, io.get());
            if (io->fd == io_fd->old_fd)
                continue;
        }

        switch (io->io_mode)
        {
            case IO_CLOSE:
            {
                if (! err)
                    err = posix_spawn_file_actions_addclose(actions, io->fd);
                break;
            }

            case IO_FILE:
            {
                CAST_INIT(const io_file_t *, io_file, io.get());
                if (! err)
                    err = posix_spawn_file_actions_addopen(actions, io->fd, io_file->filename_cstr, io_file->flags /* mode */, OPEN_MASK);
                break;
            }

            case IO_FD:
            {
                CAST_INIT(const io_fd_t *, io_fd, io.get());
                if (! err)
                    err = posix_spawn_file_actions_adddup2(actions, io_fd->old_fd /* from */, io->fd /* to */);
                break;
            }

            case IO_BUFFER:
            case IO_PIPE:
            {
                CAST_INIT(const io_pipe_t *, io_pipe, io.get());
                unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1);
                int from_fd = io_pipe->pipe_fd[write_pipe_idx];
                int to_fd = io->fd;
                if (! err)
                    err = posix_spawn_file_actions_adddup2(actions, from_fd, to_fd);


                if (write_pipe_idx > 0)
                {
                    if (! err)
                        err = posix_spawn_file_actions_addclose(actions, io_pipe->pipe_fd[0]);
                    if (! err)
                        err = posix_spawn_file_actions_addclose(actions, io_pipe->pipe_fd[1]);
                }
                else
                {
                    if (! err)
                        err = posix_spawn_file_actions_addclose(actions, io_pipe->pipe_fd[0]);

                }
                break;
            }
        }
    }