5

Is there a command runner like env, nice, nohup, etc., that can run a program with modified signals? In my case, I need something to reset SIGINT to SIG_DFL.

Why do I need this? Because non-interactive bash sets SIG_IGN for SIGINT for background processes and you can't reset it with the shell built-in trap: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=573780

upd: in bash 4.3 background subshell does not ignore SIGINT, other background programs still do

http://tiswww.case.edu/php/chet/bash/CHANGES

h. Fixed a bug that caused SIGINT and SIGQUIT to not be trappable in asynchronous subshell commands.

8
  • 1
    So why not just background the subshell?
    – mikeserv
    Jul 2, 2015 at 21:21
  • @mikeserv I'm on rhel 6 with bash 4.1
    – basin
    Jul 2, 2015 at 21:27
  • ...so update? Or maybe get a better shell.
    – mikeserv
    Jul 2, 2015 at 21:29
  • 2
    @mikeserv yeh or he could just install windows and be happy double-clicking stuff instead of writing shell script. Or not doing that at all. I'm pretty sure the OP has his own reason for not changing the operating system or the shell, and it may be better to stay on topic.
    – pqnet
    Jul 3, 2015 at 13:39
  • 1
    @mikesev Tested dash: it behaves exactly as bash 4.1. bash has been breaking POSIX, good to hear: there are many crappy parts in posix.
    – basin
    Jul 3, 2015 at 19:34

1 Answer 1

4

There is no. Very easy to write one with perl. Here's untrap script:

#!/usr/bin/perl
$SIG{INT} = "DEFAULT";
exec { $ARGV[0] } @ARGV or die "couldn't exec $ARGV[0]: $!";

Example usage:

#!/bin/bash
untrap bash -c '
    sleep 3
    echo aaa
' &
trap '' INT
wait $!

If you remove untrap prefix, Ctrl-C won't kill the script.

More versatile script:

#!/usr/bin/perl

use Getopt::Long;

GetOptions(
    'help' => sub {
        print "usage: $0 [--sig={INT|HUP|...}={IGNORE|DEFAULT}]... COMMAND [ARG]...\n";
        exit 0;
    },
    'sig=s%' =>
    sub {
        my $action = $_[2];
        my $signame = $_[1];
        die "bad action $action" unless ($action eq "IGNORE" or $action eq "DEFAULT");
        die "bad signame $signame" if ($signame eq "__DIE__" or $signame eq "__WARN__");
        $SIG{$_[1]} = $action;
    }) or exit 1;

exec { $ARGV[0] } @ARGV or die "couldn't exec $ARGV[0]: $!";
2
  • And the called process sets up it's own signal handlers. You are setting signal handlers for the Perl process.
    – vonbrand
    Mar 4, 2020 at 17:09
  • @vonbrand the called process inherits the "ignore" flag for a signal.
    – basin
    Mar 5, 2020 at 5:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.