13

Linuxでは、プログラムのシグナリングを外部から無効にすることは可能ですか?つまり、ソースコードを変更する必要はありませんか?

コンテクスト:

Linuxのbashスクリプト内からC(およびJava )プログラムを呼び出しています。bashスクリプト、およびスクリプトが(フォアグラウンドプロセスとして)起動する他のプログラムを中断したくありません。

私は使用できますが...

trap '' INT

... Ctrl C信号を無効にするbashスクリプトでは、これはプログラムコントロールがbashコードに含まれている場合にのみ機能します。つまり、Cプログラムの実行中にCtrl Cを押すと、Cプログラムが中断され、終了します。このCプログラムはいくつかの重要な操作を行っているため、中断されたくありません。このCプログラムのソースコードにアクセスできないので、Cプログラム内の信号処理は問題外です。

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

よろしく、

/ HS

4

5 に答える 5

13

プロセスシグナルマスクはに継承されるため、ターゲットをブロックして実行するexec小さなラッパープログラムを作成するだけです。SIGINT

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

このプログラムをにコンパイルするとnoint、を実行するだけ./noint ./yです。

コメントのエフェミエントノートのように、シグナルの性質も継承されるため、ラッパーにシグナルをブロックする代わりに無視させることができます。

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

(そしてもちろん、ベルトとブレースのアプローチでは、両方を行うことができます)。

于 2010-12-23T02:58:31.640 に答える
3

「trap」コマンドはこのプロセスに対してローカルであり、子には適用されません。

信号を実際にトラップするには、LD_PRELOADフックを使用して信号をハックする必要があります。これは重要なタスクであるため(ロード可能なものを内部でコンパイルする必要があります_init()sigaction()、ここでは完全なコードを含めません。SIGSEGVの例は、Phack Volume 0x0b、Issue 0x3a、Phile#0x03にあります。

nohupまたは、tailトリックを試してみてください。

nohup  your_command &
tail -F nohup.out
于 2010-12-23T02:12:36.890 に答える
0

C(およびJava)アプリケーションは、例外を処理できるように書き直す必要があることをお勧めします。実際に中断する必要がある場合、電源障害などが発生した場合はどうなりますか。

私は失敗します、J-16はお金に正解です。ユーザーはプロセスを操作する必要がありますか、それとも単に出力を見る必要がありますか(出力を見る必要さえありますか?)

于 2010-12-23T02:50:02.753 に答える
0

上で説明した解決策は、Cafによって提案された両方のコマンドを連鎖させても、私には機能しません。

しかし、私はついにこの方法で期待される動作を得ることに成功しました:

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

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

実行中にCtrl-Cを押すとchild、終了するのを待ってからAAAを出力し、2 child。信号を受信しません。

サブシェルは、PIDが表示されないようにするために使用されます。

申し訳ありませんが...これはzsh用ですが、質問はbashに関するものですが、同等のスクリプトを提供するのに十分なbashについてはわかりません。

于 2014-07-09T18:30:15.863 に答える
0

これは、それをブロックするプログラムに対してCtrl+Cのような信号を有効にするコードの例です。

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

コンパイルします:

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

それを実行します:

LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld
于 2015-07-02T09:31:59.880 に答える