获取触发某些信号的进程的 pid

发布于 2024-10-17 10:08:10 字数 70 浏览 0 评论 0原文

是否有可能找出引起某些信号的进程的进程ID。在我的场景中,我有一个进程的多个子进程正在运行,我想知道其中哪个子进程发送了信号。

Is it possible to find out the process id of the process which has caused some signal. In my scenario, I have multiple children of a process running, and I want to know which one of them sent the signal.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

扭转时空 2024-10-24 10:08:11

这是一种非阻塞方法,用于获取在 Unix 中触发了 SIGCHLD 信号的子 PID:

import os
import signal


def sigchld_handler(_sig, _frame):
    try:
        child_pid, _ = os.waitpid(-1, os.WNOHANG)
    except OSError:
        return
    print(child_pid)


signal.signal(signal.SIGCHLD, sigchld_handler)

It's a non-blocking method to get a child PID which has triggered SIGCHLD signal in Unix:

import os
import signal


def sigchld_handler(_sig, _frame):
    try:
        child_pid, _ = os.waitpid(-1, os.WNOHANG)
    except OSError:
        return
    print(child_pid)


signal.signal(signal.SIGCHLD, sigchld_handler)
小…红帽 2024-10-24 10:08:11

我相信这是不可能的 - 操作系统只是不将此信息传递给目标进程。

I believe it is not possible - the OS just does not pass this information to the target process.

握住你手 2024-10-24 10:08:10

使用 python 3(终于!)非常简单。

以下是使用 python 3.3.3 进行测试的:

#! /usr/bin/python3

import signal
import time, os

def callme(num, frame):
    pass

# register the callback:
signal.signal(signal.SIGUSR1, callme)

print("py: Hi, I'm %d, talk to me with 'kill -SIGUSR1 %d'"
      % (os.getpid(),os.getpid()))

# wait for signal info:
while True:
    siginfo = signal.sigwaitinfo({signal.SIGUSR1})
    print("py: got %d from %d by user %d\n" % (siginfo.si_signo,
                                             siginfo.si_pid,
                                             siginfo.si_uid))

It is (finally!) very simple with python 3.

The following is tested with python 3.3.3:

#! /usr/bin/python3

import signal
import time, os

def callme(num, frame):
    pass

# register the callback:
signal.signal(signal.SIGUSR1, callme)

print("py: Hi, I'm %d, talk to me with 'kill -SIGUSR1 %d'"
      % (os.getpid(),os.getpid()))

# wait for signal info:
while True:
    siginfo = signal.sigwaitinfo({signal.SIGUSR1})
    print("py: got %d from %d by user %d\n" % (siginfo.si_signo,
                                             siginfo.si_pid,
                                             siginfo.si_uid))
九八野马 2024-10-24 10:08:10

POSIX Linux 确实提供此信息,请检查 man sigaction(2): http: //linux.die.net/man/2/sigaction

在 C 语言中,我设法让它轻松运行:

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

static void my_handler(int signum, siginfo_t *siginfo, void *context) {
    printf("Got signal '%d' from process '%d' of user '%d'\n",
        signum, siginfo->si_pid, siginfo->si_uid);
}

int main(void) {
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_sigaction = &my_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &act, NULL);
    printf("Hi, my pid is %d\ntalk to me with 'kill -SIGUSR1 %d'\n", getpid(), getpid());
    while(1)
        sleep(1000);
    return 0;
}

与我的 3.1.6 vanilla 内核和 gcc 4.4.5 配合得很好——但我在 python 中找不到任何支持。

所以我开始尝试自己构建一些东西(但因为我以前从未做过 C/Python 交互,所以它可能以某种方式扭曲了......)

我或多或少地接近 http://docs.python.org/extending/extending.html 并根据 http://docs.python.org/extending/building.html#building

sigpidmodule.c

#include <Python.h>
#include <signal.h>

static PyObject *callback = NULL;

static void direct_handler(int signum, siginfo_t *siginfo, void *context) {
    int pid = (int) siginfo->si_pid;
    printf("c: Signal reached c handler: signum=%d, pid=%d, handler=%p\n", 
        signum, pid, callback);
    if ( callback != NULL ) {
        PyObject *arglist = Py_BuildValue("(i,i)", signum, pid);
        printf("c: calling python callback\n");
        PyObject *result = PyObject_CallObject(callback, arglist);
        // decrease reference counter
        Py_DECREF(arglist);
        Py_DECREF(result);
    }
}

static PyObject *sigpid_register(PyObject *self, PyObject *args) {
    PyObject *result = NULL;
    PyObject *temp;
    if ( PyArg_ParseTuple(args, "O:set_callback", &temp) ) {
        if ( !PyCallable_Check(temp) ) {
            PyErr_SetString(PyExc_TypeError, "parameter must be callable");
            return NULL;
        }
    }
    Py_XINCREF(temp);     // inc refcount on new callback
    Py_XDECREF(callback); // dec refcount on old callback
    callback = temp;      // replace old callback with new
    printf("c: callback now: %p\n", (void *) callback);
    // return None
    Py_RETURN_NONE;
}

static PyObject *sigpid_ping(PyObject *self, PyObject *args) {
    if ( callback != NULL ) {
        PyObject *arglist = Py_BuildValue("(i,i)", 42, 23);
        printf("c: calling callback...\n");
        PyObject *result = PyObject_CallObject(callback, arglist);
        // decrease ref counters
        Py_DECREF(arglist);
        Py_DECREF(result);
    }
    // return None:
    Py_RETURN_NONE;
}

static PyMethodDef SigPidMethods[] = {
    {"register", sigpid_register, METH_VARARGS, "Register callback for SIGUSR1"},
    {"ping", sigpid_ping, METH_VARARGS, "Test if callback is working"},
    {NULL, NULL, 0, NULL},
};

PyMODINIT_FUNC initsigpid(void) {
    // initialize module:
    (void) Py_InitModule("sigpid", SigPidMethods);
    // set sighandler:
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_sigaction = &direct_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &act, NULL);
}

setup.py 用于构建模块:

from distutils.core import setup, Extension

module1 = Extension('sigpid', sources= ['sigpidmodule.c'])

setup (name='SigPid', version='1.0', 
    description='SigPidingStuff', 
    ext_modules = [module1])

因此

python setup.py build

,仍然缺少使用该模块的 python 脚本:test.py

import sigpid
import time, os

def callme(num, pid):
    '''
    Callback function to be called from c module
    '''
    print "py: got %d from %d\n" % (num, pid)

# register the callback:
sigpid.register(callme)

print "py: Hi, I'm %d, talk to me with 'kill -SIGUSR1 %d'" %(os.getpid(),os.getpid())
# wait for signal while doing nothing:
while True:
    time.sleep(1)

一切都工作得很好...直到:

python test.py

或者我必须实际调用它才能获得正确的库:

PYTHONPATH=build/lib.linux-i686-2.6 python test.py

输出:

c: callback now: 0xb744f534
py: Hi, I'm 2255, talk to me with 'kill -SIGUSR1 2255'
(from other term: kill -SIGUSR1 2255)
c: Signal reached c handler: signum=10, pid=2948, handler=0xb744f534
c: calling python callback
Segmentation fault

我不知道为什么会出现这个段错误,而且我已经没有办法修复它了。我想这一定与c和python如何交互有关(我可以想到一些原因,但这只是猜测)。也许在 c-python-interaction 方面有更多经验的人可以在这里提供帮助(或者至少解释一下,问题到底是什么)。我们可能有办法解决那里的问题,至少在 Linux 上。

POSIX Linux does provide this information, check man sigaction(2): http://linux.die.net/man/2/sigaction

In C, I managed to get it running easily:

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

static void my_handler(int signum, siginfo_t *siginfo, void *context) {
    printf("Got signal '%d' from process '%d' of user '%d'\n",
        signum, siginfo->si_pid, siginfo->si_uid);
}

int main(void) {
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_sigaction = &my_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &act, NULL);
    printf("Hi, my pid is %d\ntalk to me with 'kill -SIGUSR1 %d'\n", getpid(), getpid());
    while(1)
        sleep(1000);
    return 0;
}

Works pretty well with my 3.1.6 vanilla kernel and gcc 4.4.5 -- but I could not find any support for it in python.

So i started to try and build something on my own (but since I never did C/Python-Interaction before, it's probably somehow twisted up...)

I'm more or less keeping close to the example at http://docs.python.org/extending/extending.html and building the module according to http://docs.python.org/extending/building.html#building

sigpidmodule.c

#include <Python.h>
#include <signal.h>

static PyObject *callback = NULL;

static void direct_handler(int signum, siginfo_t *siginfo, void *context) {
    int pid = (int) siginfo->si_pid;
    printf("c: Signal reached c handler: signum=%d, pid=%d, handler=%p\n", 
        signum, pid, callback);
    if ( callback != NULL ) {
        PyObject *arglist = Py_BuildValue("(i,i)", signum, pid);
        printf("c: calling python callback\n");
        PyObject *result = PyObject_CallObject(callback, arglist);
        // decrease reference counter
        Py_DECREF(arglist);
        Py_DECREF(result);
    }
}

static PyObject *sigpid_register(PyObject *self, PyObject *args) {
    PyObject *result = NULL;
    PyObject *temp;
    if ( PyArg_ParseTuple(args, "O:set_callback", &temp) ) {
        if ( !PyCallable_Check(temp) ) {
            PyErr_SetString(PyExc_TypeError, "parameter must be callable");
            return NULL;
        }
    }
    Py_XINCREF(temp);     // inc refcount on new callback
    Py_XDECREF(callback); // dec refcount on old callback
    callback = temp;      // replace old callback with new
    printf("c: callback now: %p\n", (void *) callback);
    // return None
    Py_RETURN_NONE;
}

static PyObject *sigpid_ping(PyObject *self, PyObject *args) {
    if ( callback != NULL ) {
        PyObject *arglist = Py_BuildValue("(i,i)", 42, 23);
        printf("c: calling callback...\n");
        PyObject *result = PyObject_CallObject(callback, arglist);
        // decrease ref counters
        Py_DECREF(arglist);
        Py_DECREF(result);
    }
    // return None:
    Py_RETURN_NONE;
}

static PyMethodDef SigPidMethods[] = {
    {"register", sigpid_register, METH_VARARGS, "Register callback for SIGUSR1"},
    {"ping", sigpid_ping, METH_VARARGS, "Test if callback is working"},
    {NULL, NULL, 0, NULL},
};

PyMODINIT_FUNC initsigpid(void) {
    // initialize module:
    (void) Py_InitModule("sigpid", SigPidMethods);
    // set sighandler:
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_sigaction = &direct_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &act, NULL);
}

setup.py for building the module:

from distutils.core import setup, Extension

module1 = Extension('sigpid', sources= ['sigpidmodule.c'])

setup (name='SigPid', version='1.0', 
    description='SigPidingStuff', 
    ext_modules = [module1])

building the module with

python setup.py build

So, what's still missing is the python script using the module: test.py

import sigpid
import time, os

def callme(num, pid):
    '''
    Callback function to be called from c module
    '''
    print "py: got %d from %d\n" % (num, pid)

# register the callback:
sigpid.register(callme)

print "py: Hi, I'm %d, talk to me with 'kill -SIGUSR1 %d'" %(os.getpid(),os.getpid())
# wait for signal while doing nothing:
while True:
    time.sleep(1)

Everything works very well... up to:

python test.py

or as I have to actually call it to get the lib right:

PYTHONPATH=build/lib.linux-i686-2.6 python test.py

output:

c: callback now: 0xb744f534
py: Hi, I'm 2255, talk to me with 'kill -SIGUSR1 2255'
(from other term: kill -SIGUSR1 2255)
c: Signal reached c handler: signum=10, pid=2948, handler=0xb744f534
c: calling python callback
Segmentation fault

I don't know why I get this segfault, and I'm running out of ideas to fix it. I guess it must have something to do with how c and python interact (I can think of some reasons, but it's all only guessing). Maybe someone with more experience in c-python-interaction can help here (or at least explain, what's the problem exactly). We might have a way to solve the problem there, at least on linux.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文