2011-02-11 22 views

risposta

6

E 'molto semplice, con pitone 3.

effettuano i seguenti controlli con Python 3.3.3 (finalmente!):

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

io credo che non sia possibile - il sistema operativo semplicemente non passa queste informazioni al processo di destinazione.

+0

Grazie per il chiarimento. –

-2

No, non è possibile, il sistema operativo (presumibilmente un * nix) semplicemente non fornisce questa informazione. Dovrai utilizzare un altro tipo di IPC per comunicare dai processi figli al genitore. Se non lo stai già utilizzando, dovresti controllare il modulo subprocess che facilita questo tipo di operazioni.

Ad esempio, se si imposta tubi dei tuoi processi figlio al genitore, è possibile ottenere il bambino a scrivere un messaggio al tubo quando si sarebbe in precedenza stato inviato un segnale. La tua procedura padre può utilizzare una chiamata select per attendere finché non riceve un messaggio da uno dei bambini.

Questo è solo un modo per affrontare il problema IPC; si può anche lavorare con sockets, oppure il modulo multiprocessing, tra gli altri approcci. Senza saperne di più su ciò che stai cercando di fare, è difficile dare ulteriori consigli.

+0

grazie ... Sto già usando il modulo subprocess. sto usando wait() per aspettare. Ma volevo usare signal.pause() che potesse far dormire il genitore fino a quando uno dei bambini muore. Ciò salverà i cicli della CPU. –

5

POSIX Linux non fornire queste informazioni, controllare l'uomo sigaction (2): http://linux.die.net/man/2/sigaction

In C, sono riuscito a farlo funzionare facilmente:

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

funziona abbastanza bene con la mia 3.1 .6 kernel di vaniglia e gcc 4.4.5 - ma non ho trovato alcun supporto per questo in python.

così ho iniziato a cercare di costruire qualcosa per conto mio (ma dato che non ho mai fatto C/Python-interazione prima, probabilmente in qualche modo torto ...)

sto più o meno tenere vicino alla nell'esempio a http://docs.python.org/extending/extending.html e ricostruire il modulo secondo 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 per generare il modulo:

from distutils.core import setup, Extension 

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

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

costruzione del modulo con

python setup.py build 

Quindi, ciò che ancora manca è lo script Python usando il modulo: 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) 

Tutto funziona molto bene ...fino a:

python test.py 

o come devo chiamare in realtà per ottenere la giusta lib:

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

uscita:

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 

Non so perché ho questo segfault, e sono a corto di idee per sistemarlo. Immagino che debba avere qualcosa a che fare con il modo in cui c e python interagiscono (posso pensare ad alcune ragioni, ma è tutto solo a indovinare). Forse qualcuno con più esperienza nell'interazione c-python può aiutare qui (o almeno spiegare, qual è il problema esattamente). Potremmo avere un modo per risolvere il problema lì, almeno su Linux.

Problemi correlati