Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Externally disabling signals for a Linux program

On Linux, is it possible to somehow disable signaling for programs externally... that is, without modifying their source code?

Context:

I'm calling a C (and also a Java) program from within a bash script on Linux. I don't want any interruptions for my bash script, and for the other programs that the script launches (as foreground processes).

While I can use a...

trap '' INT

... in my bash script to disable the Ctrl C signal, this works only when the program control happens to be in the bash code. That is, if I press Ctrl C while the C program is running, the C program gets interrupted and it exits! This C program is doing some critical operation because of which I don't want it be interrupted. I don't have access to the source code of this C program, so signal handling inside the C program is out of question.

#!/bin/bash

trap 'echo You pressed Ctrl C' INT 

# A C program to emulate a real-world, long-running program,
# which I don't want to be interrupted, and for which I 
# don't have the source code!
#
# File: y.c
# To build: gcc -o y y.c
#
# #include <stdio.h>
# int main(int argc, char *argv[]) {
#  printf("Performing a critical operation...\n");
#    for(;;); // Do nothing forever.
#  printf("Performing a critical operation... done.\n");
# }

./y

Regards,

/HS

like image 660
Harry Avatar asked Dec 23 '10 01:12

Harry


People also ask

Which is the signal used to interrupt and terminate a UNIX Linux program?

Ctrl-C (in older Unixes, DEL) sends an INT signal ("interrupt", SIGINT); by default, this causes the process to terminate.

What is Sigquit on Linux?

Others are only handled by the operating system. SIGQUIT = quit, generated from terminal special char. This signal usually does not terminate the running process. SIGSEGV = segmentation violation. SIGKILL = kill (cannot be caught or ignored).

What is signal in Linux programming?

A signal is an event generated by the UNIX and Linux systems in response to some condition. Upon receipt of a signal, a process may take action. A signal is just like an interrupt; when it is generated at the user level, a call is made to the kernel of the OS, which then acts accordingly.

Which signal is used to quit a program in Unix?

The SIGTERM signal is a generic signal used to cause program termination. Unlike SIGKILL , this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate. The shell command kill generates SIGTERM by default.


2 Answers

The process signal mask is inherited across exec, so you can simply write a small wrapper program that blocks SIGINT and executes the target:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        sigset_t sigs;

        sigemptyset(&sigs);
        sigaddset(&sigs, SIGINT);
        sigprocmask(SIG_BLOCK, &sigs, 0);

        if (argc > 1) {
                execvp(argv[1], argv + 1);
                perror("execv");
        } else {
                fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
        }
        return 1;
}

If you compile this program to noint, you would just execute ./noint ./y.

As ephemient notes in comments, the signal disposition is also inherited, so you can have the wrapper ignore the signal instead of blocking it:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
        struct sigaction sa = { 0 };

        sa.sa_handler = SIG_IGN;
        sigaction(SIGINT, &sa, 0);

        if (argc > 1) {
                execvp(argv[1], argv + 1);
                perror("execv");
        } else {
                fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
        }
        return 1;
}

(and of course for a belt-and-braces approach, you could do both).

like image 74
caf Avatar answered Sep 18 '22 13:09

caf


The "trap" command is local to this process, never applies to children.

To really trap the signal, you have to hack it using a LD_PRELOAD hook. This is non-trival task (you have to compile a loadable with _init(), sigaction() inside), so I won't include the full code here. You can find an example for SIGSEGV on Phack Volume 0x0b, Issue 0x3a, Phile #0x03.

Alternativlly, try the nohup and tail trick.

nohup  your_command &
tail -F nohup.out
like image 37
J-16 SDiZ Avatar answered Sep 19 '22 13:09

J-16 SDiZ