This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 5/5] posix: Use posix_spawn for wordexp


Ping (x2).

On 28/08/2019 11:09, Adhemerval Zanella wrote:
> Ping.
> 
> On 31/07/2019 15:31, Adhemerval Zanella wrote:
>> Change from previous version:
>>
>>   - Use libsupport and remove atfork usage on posix/wordexp-test.c.
>>
>> --
>>
>> This patch replaces the fork+exec by posix_spawn on wordexp, which
>> allows a better scability on Linux and simplifies the thread
>> cancellation handling.
>>
>> The only change which can not be implemented with posix_spawn the
>> /dev/null check to certify it is indeed the expected device.  I am
>> not sure how effetive this check is since /dev/null tampering means
>> something very wrong with the system and this is the least of the
>> issues.  My view is the tests is really out of the place and the
>> hardening provided is minimum.
>>
>> If the idea is still to provide such check, I think a possibilty
>> would be to open /dev/null, check it, add a dup2 file action, and
>> close the file descriptor.
>>
>> Checked on powerpc64le-linux-gnu and x86_64-linux-gnu.
>>
>> 	* include/spawn.h (__posix_spawn_file_actions_addopen): New
>> 	prototype.
>> 	* posix/spawn_faction_addopen.c (posix_spawn_file_actions_addopen):
>> 	Add internal alias.
>> 	* posix/wordexp.c (create_environment, free_environment): New
>> 	functions.
>> 	(exec_comm_child, exec_comm): Use posix_spawn instead of fork+exec.
>> 	* posix/wordexp-test.c: Use libsupport and remove atfork usage.
>> ---
>>  include/spawn.h               |   3 +
>>  posix/spawn_faction_addopen.c |   8 +-
>>  posix/wordexp-test.c          | 142 +++++++++--------------------
>>  posix/wordexp.c               | 167 ++++++++++++++++------------------
>>  4 files changed, 129 insertions(+), 191 deletions(-)
>>
>> diff --git a/include/spawn.h b/include/spawn.h
>> index 7fdd965bd7..4a0b1849da 100644
>> --- a/include/spawn.h
>> +++ b/include/spawn.h
>> @@ -11,6 +11,9 @@ __typeof (posix_spawn_file_actions_addclose)
>>  __typeof (posix_spawn_file_actions_adddup2)
>>    __posix_spawn_file_actions_adddup2 attribute_hidden;
>>  
>> +__typeof (posix_spawn_file_actions_addopen)
>> +  __posix_spawn_file_actions_addopen attribute_hidden;
>> +
>>  __typeof (posix_spawn_file_actions_destroy)
>>    __posix_spawn_file_actions_destroy attribute_hidden;
>>  
>> diff --git a/posix/spawn_faction_addopen.c b/posix/spawn_faction_addopen.c
>> index 742eb9526d..2e598de300 100644
>> --- a/posix/spawn_faction_addopen.c
>> +++ b/posix/spawn_faction_addopen.c
>> @@ -25,9 +25,9 @@
>>  /* Add an action to FILE-ACTIONS which tells the implementation to call
>>     `open' for the given file during the `spawn' call.  */
>>  int
>> -posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
>> -				  int fd, const char *path, int oflag,
>> -				  mode_t mode)
>> +__posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
>> +				    int fd, const char *path, int oflag,
>> +				    mode_t mode)
>>  {
>>    struct __spawn_action *rec;
>>  
>> @@ -60,3 +60,5 @@ posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
>>  
>>    return 0;
>>  }
>> +weak_alias (__posix_spawn_file_actions_addopen,
>> +	    posix_spawn_file_actions_addopen)
>> diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
>> index 10a0768a6b..ef780b0a65 100644
>> --- a/posix/wordexp-test.c
>> +++ b/posix/wordexp-test.c
>> @@ -15,39 +15,21 @@
>>     License along with the GNU C Library; if not, see
>>     <http://www.gnu.org/licenses/>.  */
>>  
>> -#include <sys/stat.h>
>> -#include <sys/types.h>
>> -#include <sys/mman.h>
>> +#include <wordexp.h>
>> +#include <stdio.h>
>>  #include <fcntl.h>
>> -#include <unistd.h>
>>  #include <pwd.h>
>> -#include <stdio.h>
>> -#include <stdint.h>
>>  #include <stdlib.h>
>>  #include <string.h>
>> -#include <wordexp.h>
>> +#include <sys/mman.h>
>> +
>>  #include <libc-pointer-arith.h>
>> -#include <dso_handle.h>
>> +#include <array_length.h>
>> +#include <support/xunistd.h>
>> +#include <support/check.h>
>>  
>>  #define IFS " \n\t"
>>  
>> -extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
>> -
>> -static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
>> -{
>> -  return __register_atfork (prepare, parent, child, __dso_handle);
>> -}
>> -
>> -/* Number of forks seen.  */
>> -static int registered_forks;
>> -
>> -/* For each fork increment the fork count.  */
>> -static void
>> -register_fork (void)
>> -{
>> -  registered_forks++;
>> -}
>> -
>>  struct test_case_struct
>>  {
>>    int retval;
>> @@ -57,7 +39,7 @@ struct test_case_struct
>>    size_t wordc;
>>    const char *wordv[10];
>>    const char *ifs;
>> -} test_case[] =
>> +} static test_case[] =
>>    {
>>      /* Simple word- and field-splitting */
>>      { 0, NULL, "one", 0, 1, { "one", }, IFS },
>> @@ -238,8 +220,6 @@ struct test_case_struct
>>      { WRDE_SYNTAX, NULL, "${", 0, 0, { NULL, }, IFS },      /* BZ 18043  */
>>      { WRDE_SYNTAX, NULL, "L${a:", 0, 0, { NULL, }, IFS },   /* BZ 18043#c4  */
>>      { WRDE_SYNTAX, NULL, "$[1/0]", WRDE_NOCMD, 0, {NULL, }, IFS }, /* BZ 18100 */
>> -
>> -    { -1, NULL, NULL, 0, 0, { NULL, }, IFS },
>>    };
>>  
>>  static int testit (struct test_case_struct *tc);
>> @@ -256,16 +236,14 @@ command_line_test (const char *words)
>>      printf ("we_wordv[%d] = \"%s\"\n", i, we.we_wordv[i]);
>>  }
>>  
>> -int
>> -main (int argc, char *argv[])
>> +static int
>> +do_test (int argc, char *argv[])
>>  {
>> -  const char *globfile[] = { "one", "two", "three", NULL };
>> +  const char *globfile[] = { "one", "two", "three" };
>>    char tmpdir[32];
>>    struct passwd *pw;
>>    const char *cwd;
>>    int test;
>> -  int fail = 0;
>> -  int i;
>>    struct test_case_struct ts;
>>  
>>    if (argc > 1)
>> @@ -278,30 +256,18 @@ main (int argc, char *argv[])
>>  
>>    /* Set up arena for pathname expansion */
>>    tmpnam (tmpdir);
>> -  if (mkdir (tmpdir, S_IRWXU) || chdir (tmpdir))
>> -    return -1;
>> -  else
>> -    {
>> -      int fd;
>> +  xmkdir (tmpdir, S_IRWXU);
>> +  TEST_VERIFY_EXIT (chdir (tmpdir) == 0);
>>  
>> -      for (i = 0; globfile[i]; ++i)
>> -	if ((fd = creat (globfile[i], S_IRUSR | S_IWUSR)) == -1
>> -	    || close (fd))
>> -	  return -1;
>> -    }
>> -
>> -  /* If we are not allowed to do command substitution, we install
>> -     fork handlers to verify that no forks happened.  No forks should
>> -     happen at all if command substitution is disabled.  */
>> -  if (__app_register_atfork (register_fork, NULL, NULL) != 0)
>> +  for (int i = 0; i < array_length (globfile); ++i)
>>      {
>> -      printf ("Failed to register fork handler.\n");
>> -      return -1;
>> +      int fd = xopen (globfile[i], O_WRONLY|O_CREAT|O_TRUNC,
>> +		      S_IRUSR | S_IWUSR);
>> +      xclose (fd);
>>      }
>>  
>> -  for (test = 0; test_case[test].retval != -1; test++)
>> -    if (testit (&test_case[test]))
>> -      ++fail;
>> +  for (test = 0; test < array_length (test_case); test++)
>> +    TEST_COMPARE (testit (&test_case[test]), 0);
>>  
>>    /* Tilde-expansion tests. */
>>    pw = getpwnam ("root");
>> @@ -315,8 +281,7 @@ main (int argc, char *argv[])
>>        ts.wordv[0] = pw->pw_dir;
>>        ts.ifs = IFS;
>>  
>> -      if (testit (&ts))
>> -	++fail;
>> +      TEST_COMPARE (testit (&ts), 0);
>>  
>>        ts.retval = 0;
>>        ts.env = pw->pw_dir;
>> @@ -326,8 +291,7 @@ main (int argc, char *argv[])
>>        ts.wordv[0] = "x";
>>        ts.ifs = IFS;
>>  
>> -      if (testit (&ts))
>> -	++fail;
>> +      TEST_COMPARE (testit (&ts), 0);
>>      }
>>  
>>    /* "~" expands to value of $HOME when HOME is set */
>> @@ -342,8 +306,7 @@ main (int argc, char *argv[])
>>    ts.wordv[1] = "/dummy/home/foo";
>>    ts.ifs = IFS;
>>  
>> -  if (testit (&ts))
>> -    ++fail;
>> +  TEST_COMPARE (testit (&ts), 0);
>>  
>>    /* "~" expands to home dir from passwd file if HOME is not set */
>>  
>> @@ -359,8 +322,7 @@ main (int argc, char *argv[])
>>        ts.wordv[0] = pw->pw_dir;
>>        ts.ifs = IFS;
>>  
>> -      if (testit (&ts))
>> -	++fail;
>> +      TEST_COMPARE (testit (&ts), 0);
>>      }
>>  
>>    /* Integer overflow in division.  */
>> @@ -375,37 +337,32 @@ main (int argc, char *argv[])
>>        "18446744073709551616",
>>        "170141183460469231731687303715884105728",
>>        "340282366920938463463374607431768211456",
>> -      NULL
>>      };
>>  
>> -    for (const char *const *num = numbers; *num; ++num)
>> +    for (int i = 0; i < array_length (numbers); i++)
>>        {
>>  	wordexp_t p;
>>  	char pattern[256];
>> -	snprintf (pattern, sizeof (pattern), "$[(-%s)/(-1)]", *num);
>> +	snprintf (pattern, sizeof (pattern), "$[(-%s)/(-1)]", numbers[i]);
>>  	int ret = wordexp (pattern, &p, WRDE_NOCMD);
>>  	if (ret == 0)
>>  	  {
>> -	    if (p.we_wordc != 1 || strcmp (p.we_wordv[0], *num) != 0)
>> -	      {
>> -		printf ("Integer overflow for \"%s\" failed", pattern);
>> -		++fail;
>> -	      }
>> +	    TEST_COMPARE (p.we_wordc, 1);
>> +	    TEST_COMPARE (strcmp (p.we_wordv[0], numbers[i]), 0);
>>  	    wordfree (&p);
>>  	  }
>> -	else if (ret != WRDE_SYNTAX)
>> +	else
>>  	  {
>> -	    printf ("Integer overflow for \"%s\" failed with %d",
>> -		    pattern, ret);
>> -	    ++fail;
>> +	    TEST_COMPARE (ret, WRDE_SYNTAX);
>> +	    if (ret != WRDE_SYNTAX)
>> +	      printf ("Integer overflow for \"%s\" failed with %d",
>> +		      pattern, ret);
>>  	  }
>>        }
>>    }
>>  
>> -  puts ("tests completed, now cleaning up");
>> -
>>    /* Clean up */
>> -  for (i = 0; globfile[i]; ++i)
>> +  for (int i = 0; i < array_length (globfile); ++i)
>>      remove (globfile[i]);
>>  
>>    if (cwd == NULL)
>> @@ -414,26 +371,17 @@ main (int argc, char *argv[])
>>    chdir (cwd);
>>    rmdir (tmpdir);
>>  
>> -  printf ("tests failed: %d\n", fail);
>> -
>> -  return fail != 0;
>> +  return 0;
>>  }
>>  
>>  static const char *
>>  at_page_end (const char *words)
>>  {
>>    const int pagesize = getpagesize ();
>> -  char *start = mmap (0, 2 * pagesize, PROT_READ|PROT_WRITE,
>> -		      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
>> +  char *start = xmmap (0, 2 * pagesize, PROT_READ | PROT_WRITE,
>> +		       MAP_PRIVATE | MAP_ANONYMOUS, -1);
>>  
>> -  if (start == MAP_FAILED)
>> -    return start;
>> -
>> -  if (mprotect (start + pagesize, pagesize, PROT_NONE))
>> -    {
>> -      munmap (start, 2 * pagesize);
>> -      return MAP_FAILED;
>> -    }
>> +  xmprotect (start + pagesize, pagesize, PROT_NONE);
>>  
>>    /* Includes terminating NUL.  */
>>    const size_t words_size = strlen (words) + 1;
>> @@ -472,9 +420,6 @@ testit (struct test_case_struct *tc)
>>    fflush (NULL);
>>    const char *words = at_page_end (tc->words);
>>  
>> -  if (tc->flags & WRDE_NOCMD)
>> -    registered_forks = 0;
>> -
>>    if (tc->flags & WRDE_APPEND)
>>      {
>>        /* initial wordexp() call, to be appended to */
>> @@ -486,13 +431,6 @@ testit (struct test_case_struct *tc)
>>      }
>>    retval = wordexp (words, &we, tc->flags);
>>  
>> -  if ((tc->flags & WRDE_NOCMD)
>> -      && (registered_forks > 0))
>> -    {
>> -	  printf ("FAILED fork called for WRDE_NOCMD\n");
>> -	  return 1;
>> -    }
>> -
>>    if (tc->flags & WRDE_DOOFFS)
>>        start_offs = sav_we.we_offs;
>>  
>> @@ -551,9 +489,11 @@ testit (struct test_case_struct *tc)
>>    const int page_size = getpagesize ();
>>    char *start = (char *) PTR_ALIGN_DOWN (words, page_size);
>>  
>> -  if (munmap (start, 2 * page_size) != 0)
>> -    return 1;
>> +  xmunmap (start, 2 * page_size);
>>  
>>    fflush (NULL);
>>    return bzzzt;
>>  }
>> +
>> +#define TEST_FUNCTION_ARGV do_test
>> +#include <support/test-driver.c>
>> diff --git a/posix/wordexp.c b/posix/wordexp.c
>> index 22c6d18a9c..e1aafcaceb 100644
>> --- a/posix/wordexp.c
>> +++ b/posix/wordexp.c
>> @@ -25,33 +25,18 @@
>>  #include <libintl.h>
>>  #include <paths.h>
>>  #include <pwd.h>
>> -#include <signal.h>
>>  #include <stdbool.h>
>>  #include <stdio.h>
>> -#include <stdlib.h>
>>  #include <string.h>
>>  #include <sys/param.h>
>> -#include <sys/stat.h>
>> -#include <sys/time.h>
>> -#include <sys/types.h>
>> -#include <sys/types.h>
>>  #include <sys/wait.h>
>>  #include <unistd.h>
>> -#include <wchar.h>
>>  #include <wordexp.h>
>> -#include <kernel-features.h>
>> +#include <spawn.h>
>>  #include <scratch_buffer.h>
>> -
>> -#include <libc-lock.h>
>>  #include <_itoa.h>
>> -
>> -/* Undefine the following line for the production version.  */
>> -/* #define NDEBUG 1 */
>>  #include <assert.h>
>>  
>> -/* Get some device information.  */
>> -#include <device-nrs.h>
>> -
>>  /*
>>   * This is a recursive-descent-style word expansion routine.
>>   */
>> @@ -812,61 +797,90 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
>>    return WRDE_SYNTAX;
>>  }
>>  
>> +static char **
>> +create_environment (void)
>> +{
>> +  size_t s = 0;
>> +
>> +  /* Calculate total environment size, including 'IFS' if is present.  */
>> +  for (char **ep = __environ; *ep != NULL; ep++, s++);
>> +
>> +  /* Include final NULL pointer.  */
>> +  char **newenviron = malloc (s * sizeof (char*));
>> +  if (newenviron == NULL)
>> +    return NULL;
>> +
>> +  /* Copy current environment excluding 'IFS', to make sure the subshell
>> +     doesn't field-split on our behalf. */
>> +  size_t i, j;
>> +  for (i = 0, j = 0; i < s; i++)
>> +    if (strncmp (__environ[i], "IFS=", sizeof ("IFS=")-1) != 0)
>> +      newenviron[j++] = __strdup (__environ[i]);
>> +  newenviron[j] = NULL;
>> +
>> +  return newenviron;
>> +}
>> +
>> +static void
>> +free_environment (char **environ)
>> +{
>> +  for (char **ep = environ; *ep != NULL; ep++)
>> +    free (*ep);
>> +  free (environ);
>> +}
>> +
>>  /* Function called by child process in exec_comm() */
>> -static inline void
>> -__attribute__ ((always_inline))
>> -exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
>> +static pid_t
>> +exec_comm_child (char *comm, int *fildes, bool showerr, bool noexec)
>>  {
>> -  const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
>> +  pid_t pid = -1;
>>  
>> -  /* Execute the command, or just check syntax? */
>> -  if (noexec)
>> -    args[1] = "-nc";
>> +  /* Execute the command, or just check syntax?  */
>> +  const char *args[] = { _PATH_BSHELL, noexec ? "-nc" : "-c", comm, NULL };
>>  
>> -  /* Redirect output.  */
>> -  if (__glibc_likely (fildes[1] != STDOUT_FILENO))
>> -    {
>> -      __dup2 (fildes[1], STDOUT_FILENO);
>> -      __close (fildes[1]);
>> -    }
>> -  else
>> -    /* Reset the close-on-exec flag (if necessary).  */
>> -    __fcntl (fildes[1], F_SETFD, 0);
>> +  posix_spawn_file_actions_t fa;
>> +  /* posix_spawn_file_actions_init does not fail.  */
>> +  __posix_spawn_file_actions_init (&fa);
>>  
>> -  /* Redirect stderr to /dev/null if we have to.  */
>> -  if (showerr == 0)
>> +  /* Redirect output.  For check syntax only (noexec being true), exec_comm
>> +     explicits sets fildes[1] to -1, so check its value to avoid a failure in
>> +     __posix_spawn_file_actions_adddup2.  */
>> +  if (fildes[1] != -1)
>>      {
>> -      struct stat64 st;
>> -      int fd;
>> -      __close (STDERR_FILENO);
>> -      fd = __open (_PATH_DEVNULL, O_WRONLY);
>> -      if (fd >= 0 && fd != STDERR_FILENO)
>> +      if (__glibc_likely (fildes[1] != STDOUT_FILENO))
>>  	{
>> -	  __dup2 (fd, STDERR_FILENO);
>> -	  __close (fd);
>> +	  if (__posix_spawn_file_actions_adddup2 (&fa, fildes[1],
>> +						  STDOUT_FILENO) != 0
>> +	      || __posix_spawn_file_actions_addclose (&fa, fildes[1]) != 0)
>> +	    goto out;
>>  	}
>> -      /* Be paranoid.  Check that we actually opened the /dev/null
>> -	 device.  */
>> -      if (__builtin_expect (__fxstat64 (_STAT_VER, STDERR_FILENO, &st), 0) != 0
>> -	  || __builtin_expect (S_ISCHR (st.st_mode), 1) == 0
>> -#if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
>> -	  || st.st_rdev != __gnu_dev_makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR)
>> -#endif
>> -	  )
>> -	/* It's not the /dev/null device.  Stop right here.  The
>> -	   problem is: how do we stop?  We use _exit() with an
>> -	   hopefully unusual exit code.  */
>> -	_exit (90);
>> +      else
>> +	/* Reset the close-on-exec flag (if necessary).  */
>> +	if (__posix_spawn_file_actions_adddup2 (&fa, fildes[1], fildes[1])
>> +	    != 0)
>> +	  goto out;
>>      }
>>  
>> -  /* Make sure the subshell doesn't field-split on our behalf. */
>> -  __unsetenv ("IFS");
>> +  /* Redirect stderr to /dev/null if we have to.  */
>> +  if (!showerr)
>> +    if (__posix_spawn_file_actions_addopen (&fa, STDERR_FILENO, _PATH_DEVNULL,
>> +					    O_WRONLY, 0) != 0)
>> +      goto out;
>> +
>> +  char **newenv = create_environment ();
>> +  if (newenv == NULL)
>> +    goto out;
>>  
>> -  __close (fildes[0]);
>> -  __execve (_PATH_BSHELL, (char *const *) args, __environ);
>> +  /* pid is unset if posix_spawn fails, so it keep the original value
>> +     of -1.  */
>> +  __posix_spawn (&pid, _PATH_BSHELL, &fa, NULL, (char *const *) args, newenv);
>>  
>> -  /* Bad.  What now?  */
>> -  abort ();
>> +  free_environment (newenv);
>> +
>> +out:
>> +  __posix_spawn_file_actions_destroy (&fa);
>> +
>> +  return pid;
>>  }
>>  
>>  /* Function to execute a command and retrieve the results */
>> @@ -884,13 +898,13 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
>>    size_t maxnewlines = 0;
>>    char buffer[bufsize];
>>    pid_t pid;
>> -  int noexec = 0;
>> +  bool noexec = false;
>>  
>>    /* Do nothing if command substitution should not succeed.  */
>>    if (flags & WRDE_NOCMD)
>>      return WRDE_CMDSUB;
>>  
>> -  /* Don't fork() unless necessary */
>> +  /* Don't posix_spawn() unless necessary */
>>    if (!comm || !*comm)
>>      return 0;
>>  
>> @@ -898,19 +912,15 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
>>      return WRDE_NOSPACE;
>>  
>>   again:
>> -  if ((pid = __fork ()) < 0)
>> +  pid = exec_comm_child (comm, fildes, noexec ? false : flags & WRDE_SHOWERR,
>> +			 noexec);
>> +  if (pid < 0)
>>      {
>> -      /* Bad */
>>        __close (fildes[0]);
>>        __close (fildes[1]);
>>        return WRDE_NOSPACE;
>>      }
>>  
>> -  if (pid == 0)
>> -    exec_comm_child (comm, fildes, noexec ? 0 : flags & WRDE_SHOWERR, noexec);
>> -
>> -  /* Parent */
>> -
>>    /* If we are just testing the syntax, only wait.  */
>>    if (noexec)
>>      return (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) == pid
>> @@ -1091,7 +1101,7 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
>>    /* Check for syntax error (re-execute but with "-n" flag) */
>>    if (buflen < 1 && status != 0)
>>      {
>> -      noexec = 1;
>> +      noexec = true;
>>        goto again;
>>      }
>>  
>> @@ -1143,26 +1153,9 @@ parse_comm (char **word, size_t *word_length, size_t *max_length,
>>  	      /* Go -- give script to the shell */
>>  	      if (comm)
>>  		{
>> -#ifdef __libc_ptf_call
>> -		  /* We do not want the exec_comm call to be cut short
>> -		     by a thread cancellation since cleanup is very
>> -		     ugly.  Therefore disable cancellation for
>> -		     now.  */
>> -		  // XXX Ideally we do want the thread being cancelable.
>> -		  // XXX If demand is there we'll change it.
>> -		  int state = PTHREAD_CANCEL_ENABLE;
>> -		  __libc_ptf_call (__pthread_setcancelstate,
>> -				   (PTHREAD_CANCEL_DISABLE, &state), 0);
>> -#endif
>> -
>> +		  /* posix_spawn already handles thread cancellation.  */
>>  		  error = exec_comm (comm, word, word_length, max_length,
>>  				     flags, pwordexp, ifs, ifs_white);
>> -
>> -#ifdef __libc_ptf_call
>> -		  __libc_ptf_call (__pthread_setcancelstate,
>> -				   (state, NULL), 0);
>> -#endif
>> -
>>  		  free (comm);
>>  		}
>>  
>>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]