Hi,
On Tuesday 16 February 2016 18:06:44 Maros Zatko wrote:
 Patch registers SIGTSTP hook where it sends reset terminal color
 control sequence.
 --- 
IMHO the commit message and the patch (in form of comments) could get
more explanation of what is being done, and why each step is done.
Signal handling is a tricky part of C programming, so everything needs
to be properly documented in order to not break it in the future.
  fish/fish.c | 72
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 72 insertions(+)
 
 diff --git a/fish/fish.c b/fish/fish.c
 index d26f8b3..b579898 100644
 --- a/fish/fish.c
 +++ b/fish/fish.c
 @@ -73,6 +73,11 @@ static void cleanup_readline (void);
  static char *decode_ps1 (const char *);
  static void add_history_line (const char *);
  #endif
 +static void set_stophandler (void);
 +static void restore_stophandler (void);
 +static void user_control_z (int sig);
 +
 +static void (*otstpfn) = SIG_DFL;
  
  static int override_progress_bars = -1;
  static struct progress_bar *bar = NULL;
 @@ -159,6 +164,64 @@ usage (int status)
    exit (status);
  }
  
 +/*
 + * Set the TSTP handler.
 + */
 +static void
 +set_stophandler (void)
 +{
 +  otstpfn = signal (SIGTSTP, user_control_z);
 +}
 +
 +/*
 + * Restore the TSTP handler.
 + */
 +static void
 +restore_stophandler (void)
 +{
 +  signal (SIGTSTP, otstpfn);
 +} 
sigaction() is used to install the signal handler for SIGTSTP, but
signal() is used in these functions (called from the signal handler):
this is a bad, you should not mix sigaction() and signal() usages;
see the sigaction() documentation [1].
 +static void
 +user_control_z (int sig)
 +{
 +  sigset_t oset, set;
 +
 +#ifdef HAVE_LIBREADLINE
 +  /* Cleanup readline, unhook from terminal */
 +  rl_free_line_state ();
 +  rl_cleanup_after_signal ();
 +#endif
 +
 +  /* Reset terminal color */
 +#define RESETCOLOR "\033[0m"
 +  printf (RESETCOLOR);
 +  fflush (stdout); 
Neither printf() nor fflush() are async-signal-safe functions, and
thus you cannot use them in a signal handler; see [2] for the list of
supported functions.  You can use write() and fsync() though.
 +  /* Unblock SIGTSTP. */
 +  sigemptyset (&set);
 +  sigaddset (&set, SIGTSTP);
 +  sigprocmask (SIG_UNBLOCK, &set, NULL); 
Sounds like this is what the SA_NODEFER flag for sigaction() does.
 +
 +  restore_stophandler ();
 +
 +  /* Stop ourselves. */
 +  kill (0, SIGTSTP);
 +
 +  /* Now we're stopped ... */
 +
 +  /* Reset the curses SIGTSTP signal handler. */
 +  set_stophandler (); 
IMHO a better way would be to save the previous SIGTSTP signal handler
(which sigaction() gives you), and call it manually
 +
 +#ifdef HAVE_LIBREADLINE
 +  /* Restore readline state */
 +  rl_reset_after_signal ();
 +#endif
 +
 +  /* Reset the signals. */
 +  sigprocmask (SIG_SETMASK, &oset, NULL);
 +}
 +
  int
  main (int argc, char *argv[])
  {
 @@ -439,6 +502,15 @@ main (int argc, char *argv[])
        exit (EXIT_FAILURE);
    }
  
 +  /* Register ^Z handler. We need it to reset terminal colors
 +   */
 +  if (is_interactive) {
 +    memset (&sa, 0, sizeof sa);
 +    sa.sa_handler = user_control_z;
 +    sa.sa_flags = SA_RESTART;
 +    sigaction (SIGTSTP, &sa, NULL);
 +  }
 +
    /* Old-style -i syntax?  Since -a/-d/-N and -i was disallowed
     * previously, if we have -i without any drives but with something
     * on the command line, it must be old-style syntax.
  
[1] 
http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
[2] 
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#...
Thanks,
-- 
Pino Toscano