On Tue, Mar 08, 2011 at 11:19:25AM -0500, Chet Ramey wrote:
> On 3/8/11 5:29 AM, Dr. Werner Fink wrote:
> 
> >> One thing that has changed is that an interactive shell will no longer
> >> attempt to write the history file if it's killed by a signal, since that
> >> causes many functions to be executed that are not safe to call from a
> >> signal handler.  If you're in the habit of trying to exit the shell by
> >> closing the terminal window, which causes the shell to be killed by SIGHUP
> >> (I think, maybe SIGTERM), the history will not be saved.
> > 
> > That will cause a lot of bugreports.  Just a question: could an atexit()
> > handler an option or an other way the bash could make use use an extra
> > (sig)longjmp()/(sig)setjmp() after increasing an atomic control variable
> > in the signal handlers for SIGHUP/SIGTERM to run all things done short
> > before exit.
> 
> The signal handling is already split up between a handler and a function
> that does the processing when it's `safe'.  The problem is that there are
> some signals that have to be handled immediately because it's really not
> possible to continue after receiving them (e.g., SIGSEGV), and some cases
> where you have to handle the signal immediately because you're not in a
> position to wait until a safe time (e.g., when reading input from the
> terminal using read(2)).  This is the latter case.
> 
> I might be able to finesse this particular case based on the state that
> readline exports to the calling application.  Another option is to take
> advantage of the fact that bash installs the SIGHUP handler without the
> SA_RESTART flag, but that requires more extensive changes.

Does this mean that the attached patch could also not work
on some systems? Or does this interfere with the readline
library?

That would be a problem as I'm pretty sure that most users
will see this a major bug.  Even sysadmins will open a bug
as a simple shutdown will miss their last few command lines.


   Werner

-- 
  "Having a smoking section in a restaurant is like having
          a peeing section in a swimming pool." -- Edward Burr
--- shell.c
+++ shell.c	2011-03-08 16:46:50.201047812 +0000
@@ -261,6 +261,9 @@ static const struct {
   { (char *)0x0, Int, (int *)0x0, (char **)0x0 }
 };
 
+volatile procenv_t terminating_now;
+volatile sig_atomic_t jump_with_sig;
+
 /* These are extern so execute_simple_command can set them, and then
    longjmp back to main to execute a shell script, instead of calling
    main () again and resulting in indefinite, possibly fatal, stack
@@ -379,6 +382,20 @@ main (argc, argv, env)
   if (code)
     exit (2);
 
+  /* Catch signals here */
+  if (setjmp (terminating_now))
+    {
+      int sig = jump_with_sig;
+      terminating_signal = 0;	/* keep macro from re-testing true. */
+      run_exit_trap ();
+      if (interactive_shell && sig != SIGABRT)
+	maybe_save_shell_history ();
+      set_signal_handler (sig, SIG_DFL);
+      kill (getpid (), sig);
+      _exit(0);
+    }
+  jump_with_sig = 0;
+
   xtrace_init ();
 
 #if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
--- sig.c
+++ sig.c	2011-03-08 16:48:26.707926125 +0000
@@ -503,10 +503,6 @@ termsig_sighandler (sig)
   /* XXX - should this also trigger when interrupt_immediately is set? */
   if (terminate_immediately)
     {
-#if defined (HISTORY)
-      /* XXX - will inhibit history file being written */
-      history_lines_this_session = 0;
-#endif
       terminate_immediately = 0;
       termsig_handler (sig);
     }
@@ -514,6 +510,9 @@ termsig_sighandler (sig)
   SIGRETURN (0);
 }
 
+extern volatile procenv_t terminating_now;
+extern volatile sig_atomic_t jump_with_sig;
+
 void
 termsig_handler (sig)
      int sig;
@@ -551,9 +550,10 @@ termsig_handler (sig)
   loop_level = continuing = breaking = funcnest = 0;
   executing_list = comsub_ignore_return = return_catch_flag = 0;
 
-  run_exit_trap ();
-  set_signal_handler (sig, SIG_DFL);
-  kill (getpid (), sig);
+  terminating_signal = 0;      /* keep macro from re-testing true. */
+
+  jump_with_sig = sig;
+  longjmp(terminating_now, 1);
 }
 
 /* What we really do when SIGINT occurs. */

Reply via email to