miércoles, 17 de diciembre de 2014

Manejo de Procesos y señales POSIX con Qt


Qt no integra ninguna solución que encapsule y simplifique la gestión de señales POSIX, puesto que éstas no están disponibles en sistemas operativos que no soporten dicha especificación.

Aun así en la documentación de Qt se describe una forma de usar manejadores de señales POSIX. Realmente basta con que el manejador de señal haga algo que provoque que Qt emita una señal y después retorne. Al volver a la secuencia normal de ejecución del programa, se emitiría la señal de Qt invocando el slot al que está conectada, desde donde se ejecutarían de forma segura las operaciones que fueran necesarias.

Para esta entrada he creado una clase en C++ llamada QPosixSignalListener que permite abstraer todo el proceso de gestión de señales. Me basé en el artículo de la documentación oficial que trata sobre manejo de señales.

Diagrama de uso de la clase:



Interfaz de la clase:

class QPosixSignalListener : public QObject
{
    Q_OBJECT
public:
    /** Constructor. Setea las señales y crea
     *  los sockets correspondientes
     *
     *  @param parent Padre del objeto
     ***/
    QPosixSignalListener(QObject *parent = 0);

    ~QPosixSignalListener(){}

    // Unix signal handlers.
    static void hupSignalHandler(int);
    static void termSignalHandler(int);
    static void usr1SignalHandler(int);
    static void usr2SignalHandler(int);

    // Set the Unix signal handlers
    static int setup_unix_signal_handlers();

private slots:

    // Qt signal handlers.
    void handlerQt_SIGHUP();
    void handlerQt_SIGTERM();
    void handlerQt_SIGUSR1();
    void handlerQt_SIGUSR2();

signals:

    // Signals
    void sigHUP();
    void sigTERM();
    void sigUSR1();
    void sigUSR2();

private:

    // sockets
    static int socketSIGHUP[2];
    static int socketSIGTERM[2];
    static int socketSIGUSR1[2];
    static int socketSIGUSR2[2];

    // Socket Notifiers
    QSocketNotifier *skNotifierHUP;
    QSocketNotifier *skNotifierTERM;
    QSocketNotifier *skNotifierUSR1;
    QSocketNotifier *skNotifierUSR2;
};

La clase puede manejar las señales SIGHUP, SIGTERM, SIGUSR1 y SIGUSR2. Puedes modificarla para que soporte otras.


USO:





Cuando el proceso recibe una señal (soportada) el objeto emite una señal de Qt.

Para usar la clase solo basta con instanciar un objeto y conectar una de sus señales a un slot cualquiera. Ejemplo:


    QPosixSignalListener *signalListener=new QPosixSignalListener();
    
    QObject::connect(signalListener,SIGNAL(sigUSR1()),cuadroAzul,SLOT(mover()));


En este caso cuando se reciba la señal SIGUSR1 entonces se ejecuta el slot mover()




Para probar la clase te puedes descargar este proyecto de Qt que ya tiene un main listo para correr: 
https://github.com/Eitol/QPosixSignalListener/archive/master.zip

Abrelo con QtCreator (recuerda eliminar antes el archivo QPosixSignalListener.pro.user)

Córrelo y envíale señales desde una terminal. 

kill -s SIGUSR1 PID // donde PID es el pid del proceso




Si quieres enviarle señales desde otro programa en Qt puedes ver como se hace aqui:
http://wannabe-programmer.blogspot.com/2014/12/enviar-senales-unix-con-qt.html

Este es el vídeo de la corrida del proyecto



















Links relacionados:

No hay comentarios:

Publicar un comentario