En C ++ cuando se interrumpe con ctrl-c, llame a una función con argumentos (que no sean el número de señal) antes de morir

Quiero escribir algunas líneas adicionales en un archivo cuando se interrumpe con ctrl-c antes de que el progtwig muera. Sin embargo, la ubicación del archivo no está codificada, por lo que necesito algo más que el manejo normal de interrupciones, como se explica aquí . ¿Cuál es la mejor manera de hacer esto?


Motivación:
Estoy haciendo simulaciones de elementos finitos dependientes del tiempo. A veces olvido o estimo mal un tmax razonable y la simulación tardaría mucho tiempo en completarse, así que lo interrumpo con ctrl-c. Sin embargo, todavía quiero usar los datos generados hasta ese momento. En particular, hay un archivo xml que necesita unas cuantas líneas agregadas después de que se termina la simulación para cerrar las tags. Por supuesto, es posible hacerlo a mano, pero es un dolor, así que estoy intentando automatizarlo.

Basándonos en la respuesta a ” ¿Cómo puedo detectar un evento ctrl-c? (C ++) ” podemos instalar un controlador de señal que simplemente genera una excepción. Luego podemos capturar la excepción y ejecutar cualquier código c ++ estándar que nos guste.

Aquí hay un ejemplo de trabajo:

#include  #include  #include  #include  class InterruptException : public std::exception { public: InterruptException(int s) : S(s) {} int S; }; void sig_to_exception(int s) { throw InterruptException(s); } int main() { // Taken from answer to "How can I catch a ctrl-c event? (C++)" struct sigaction sigIntHandler; sigIntHandler.sa_handler = sig_to_exception; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, NULL); try { std::cout << "Inside try" << std::endl; // Do something with output so the loop doesn't get optimised out double i = 0; while(i < 1e30) {i++;} // loop until interrupted std::cout << i << std::endl; } catch(InterruptException& e) { std::cout << "Write something to file" << std::endl; std::cout << "Caught signal " << eS << std::endl; return 1; } return 0; } 

Este enfoque tiene al menos un inconveniente: tenemos que envolver todo después de instalar el controlador en un bash, de lo contrario, las señales de interrupción causarán un aborto ().

Un esquema común para el código científico basado en bucles es tener un booleano sig_atomic_t volátil global que indique si se detectó una señal y agregarla a la condición del bucle.

p.ej

 volatile sig_atomic_t interrupted=false; ... void signal_handler(int s) { // ... interrupted=true; } ... while (!converged && !interrupted) { // Perform computations } // Save file properly