2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1988, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A/* Copyright (c) 1988 AT&T */ 2N/A/* All Rights Reserved */ 2N/A * Things needed by the cancellation cleanup handler. 2N/A * Daemon thread whose sole function is to reap an abandoned child. 2N/A * Cancellation cleanup handler. 2N/A * If we were cancelled in waitpid(), create a daemon thread to 2N/A * reap our abandoned child. No other thread can do this for us. 2N/A * It would be better if there were a system call to disinherit 2N/A * a child process (give it to init, just as though we exited). 2N/A if (
cup->
pid != 0) {
/* we were cancelled; abandoning our pid */ 2N/A * There are no remaining threads in system(), so 2N/A * restore the SIGINT and SIGQUIT signal actions. 2N/A /* exec for group */ 2N/A * Initialize the posix_spawn() attributes structure. 2N/A * The setting of POSIX_SPAWN_WAITPID_NP ensures that no 2N/A * wait-for-multiple wait() operation will reap our child 2N/A * and that the child will not be automatically reaped due 2N/A * to the disposition of SIGCHLD being set to be ignored. 2N/A * Only a specific wait for the specific pid will be able 2N/A * to reap the child. Since no other thread knows the pid 2N/A * of our child, this should be safe enough. 2N/A * The POSIX_SPAWN_NOEXECERR_NP flag tells posix_spawn() not 2N/A * to fail if the shell cannot be executed, but rather cause 2N/A * a child to be created that simply performs _exit(127). 2N/A * This is in order to satisfy the Posix requirement on system(): 2N/A * The system function shall behave as if a child process were 2N/A * created using fork(), and the child process invoked the sh 2N/A * utility using execl(). If some error prevents the command 2N/A * language interpreter from executing after the child process 2N/A * is created, the return value from system() shall be as if 2N/A * the command language interpreter had terminated using 2N/A * exit(127) or _exit(127). 2N/A * The POSIX spec for system() requires us to block SIGCHLD, 2N/A * the rationale being that the process's signal handler for 2N/A * SIGCHLD, if any, should not be called when our child exits. 2N/A * This doesn't work for a multithreaded process because some 2N/A * other thread could receive the SIGCHLD. 2N/A * The above setting of POSIX_SPAWN_NOSIGCHLD_NP ensures that no 2N/A * SIGCHLD signal will be posted for our child when it exits, so 2N/A * we don't have to block SIGCHLD to meet the intent of the spec. 2N/A * We block SIGCHLD anyway, just because the spec requires it. 2N/A * Tell posix_spawn() to restore the signal mask in the child. 2N/A * We are required to set the disposition of SIGINT and SIGQUIT 2N/A * to be ignored for the duration of the system() operation. 2N/A * We allow more than one thread to call system() concurrently by 2N/A * keeping a count of such threads. The signal actions are set 2N/A * to SIG_IGN when the first thread calls system(). They are 2N/A * restored in cleanup() when the last thread exits system(). 2N/A * However, system() is still MT-unsafe because sigaction() has 2N/A * a process-wide effect and some other thread may also be 2N/A * setting the signal actions for SIGINT or SIGQUIT. 2N/A * If SIGINT and SIGQUIT were not already SIG_IGN, tell 2N/A * posix_spawn() to make them SIG_DFL in the child, 2N/A * else leave them as SIG_IGN in the child. 2N/A * system() is a cancellation point and so is waitpid().