Domanda

In Linux, è possibile disabilitare segnalazione in qualche modo per programmi esternamente ... cioè, senza modificare il codice sorgente?

Contesto:

sto chiamando un C ( e anche una Java) programma all'interno di uno script bash su Linux. Non voglio interruzioni per il mio script bash, e per gli altri programmi che i lanci di script (come processi in primo piano).

Anche se posso usare un ...

trap '' INT

... nel mio script bash per disattivare il segnale di C Ctrl, questo funziona solo quando il controllo del programma sembra essere nel codice bash. Cioè, se premo Ctrl C mentre il programma C è in esecuzione, il programma C viene interrotto e esce! Questo programma C sta facendo qualche operazione critica a causa del quale io non lo voglio essere interrotto. Non ho accesso al codice sorgente di questo programma C, in modo da gestire all'interno del programma C segnale è fuori questione.

#!/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

Saluti,

/ HS

È stato utile?

Soluzione

La maschera segnale di processo è ereditata attraverso exec, in modo da poter semplicemente scrivere un piccolo programma wrapper che blocca SIGINT ed esegue il 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;
}

Se si compila a programmi noint, si sarebbe solo eseguire ./noint ./y.

Come nota ephemient nei commenti, la disposizione di segnale è ereditata, in modo da poter avere l'involucro ignorare il segnale, invece di bloccarlo:

#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;
}

(e, naturalmente, per una cintura e bretelle si avvicinano, si poteva fare entrambe le cose).

Altri suggerimenti

Il comando "trappola" è locale a questo processo, non si applica ai bambini.

Per davvero intrappolare il segnale, bisogna incidere con un gancio LD_PRELOAD. Questo è compito non banale (si deve compilare un caricabile con _init(), sigaction() all'interno), quindi non includere il codice completo qui. È possibile trovare un esempio per SIGSEGV su Phack Volume 0x0b, 0x3a Emissione, Phile # 0x03 .

Alternativlly, provare la nohup e tail trucco.

nohup  your_command &
tail -F nohup.out

vorrei suggerire che il vostro C (e Java) esigenze applicative riscrittura in modo che possa gestire un'eccezione, cosa succede se si ha veramente bisogno di essere interrotto, il potere non riesce, ecc ...

I che non riesce, J-16 è proprio sul prezzo. Fa l'utente necessità di interract con il processo, o semplicemente vedere l'output (fanno anche bisogno di vedere l'uscita?)

Le soluzioni precedentemente descritti sono non funziona per me, anche concatenando i due comandi proposti dai CAF.

Comunque, ho finalmente riuscito a ottenere il comportamento previsto in questo modo:

#!/bin/zsh
setopt MONITOR
TRAPINT() { print AAA }

print 1
( ./child & ; wait)
print 2

Se premo Ctrl-C, mentre child è in esecuzione, attenderà che esce, allora stamperà AAA e 2. child non riceverà alcun segnale.

Il sottoshell viene utilizzato per impedire il PID vengano visualizzati.

E scusate ... questo è per zsh anche se la domanda è per bash, ma io non ne so abbastanza bash per fornire uno script equivalente.

Questo è esempio di codice di segnali di abilitazione come Ctrl + C per programmi che bloccano.

fixControlC.c

#include <stdio.h>
#include <signal.h>
int sigaddset(sigset_t *set, int signo) {
    printf("int sigaddset(sigset_t *set=%p, int signo=%d)\n", set, signo);
    return 0;
}

compilarlo:

gcc -fPIC -shared -o fixControlC.so fixControlC.c

eseguirlo:

LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top