Subject: bug#8705: 23.3; Emacs occasionally crashes (segfault) just after starting it

From: Troels Nielsen <[email-masked]>
Date: Fri, 6 Jul 2012 22:32:46 +0200

It appears this is due to Fcall_process not restoring environ before
after UNBLOCK_INPUT. This is too late in your case.

The patch below against trunk, ought to fix it with minimal
intervention. But I think a better fix would be to abandon the use of
vfork and just use fork (which should be almost as fast), as the work
in the child process after vfork is undefined behavior as far as I can
understand.

Regards
Troels

=== modified file 'src/callproc.c'
*** src/callproc.c	2012-07-05 18:35:48 +0000
--- src/callproc.c	2012-07-06 20:05:44 +0000
***************
*** 494,502 ****
      }

    {
-     /* child_setup must clobber environ in systems with true vfork.
-        Protect it from permanent change.  */
-     register char **save_environ = environ;
      register int fd1 = fd[1];
      int fd_error = fd1;
  #ifdef HAVE_WORKING_VFORK
--- 494,499 ----
***************
*** 619,624 ****
--- 616,624 ----
        int volatile sa_must_free_volatile = sa_must_free;
        ptrdiff_t volatile sa_count_volatile = sa_count;
        unsigned char const **volatile new_argv_volatile = new_argv;
+       /* child_setup must clobber environ in systems with true vfork.
+          Protect it from permanent change.  */
+       char ** volatile save_environ = environ;

        pid = vfork ();

***************
*** 633,664 ****
        sa_must_free = sa_must_free_volatile;
        sa_count = sa_count_volatile;
        new_argv = new_argv_volatile;
-     }

!     if (pid == 0)
!       {
! 	if (fd[0] >= 0)
! 	  emacs_close (fd[0]);
  #ifdef HAVE_SETSID
! 	setsid ();
  #endif
  #if defined (USG)
! 	setpgrp ();
  #else
! 	setpgrp (pid, pid);
  #endif /* USG */

! 	/* GConf causes us to ignore SIGPIPE, make sure it is restored
! 	   in the child.  */
! 	signal (SIGPIPE, SIG_DFL);
  #ifdef HAVE_WORKING_VFORK
! 	pthread_sigmask (SIG_SETMASK, &procmask, 0);
  #endif

! 	child_setup (filefd, fd1, fd_error, (char **) new_argv,
! 		     0, current_dir);
!       }
!
      UNBLOCK_INPUT;

  #ifdef HAVE_WORKING_VFORK
--- 633,664 ----
        sa_must_free = sa_must_free_volatile;
        sa_count = sa_count_volatile;
        new_argv = new_argv_volatile;

!       if (pid == 0)
!         {
!           if (fd[0] >= 0)
!             emacs_close (fd[0]);
  #ifdef HAVE_SETSID
!           setsid ();
  #endif
  #if defined (USG)
!           setpgrp ();
  #else
!           setpgrp (pid, pid);
  #endif /* USG */

!           /* GConf causes us to ignore SIGPIPE, make sure it is restored
!              in the child.  */
!           signal (SIGPIPE, SIG_DFL);
  #ifdef HAVE_WORKING_VFORK
!           pthread_sigmask (SIG_SETMASK, &procmask, 0);
  #endif

!           child_setup (filefd, fd1, fd_error, (char **) new_argv,
!                        0, current_dir);
!         }
!       environ = save_environ;
!     }
      UNBLOCK_INPUT;

  #ifdef HAVE_WORKING_VFORK
***************
*** 673,681 ****
      if (fd_error >= 0)
        emacs_close (fd_error);
  #endif /* not MSDOS */
-
-     environ = save_environ;
-
      /* Close most of our fd's, but not fd[0]
         since we will use that to read input from.  */
      emacs_close (filefd);
--- 673,678 ----