Python script hangs after SIGINT "terminate called without an active exception when"

I have a python app that collects data from a sensor. The driver for the sensor is closed source and I have written a wrapper around it to simplify its use. The entire application runs on Linux. The program has the following flow.

  1. Python call into driver setup. This starts one std::thread that I control which polls the sensor and places the resulting data into an std::queue. It also calls the closed source driver startup code which appears to start a couple of threads.
  2. Python main thread starts looping picking things off of the queue of data from the sensor via a call into the c++ driver (driver.getData). Once it has the data it does some buffering and after a fixed number of samples are aggregated they are written to a file.
  3. Eventually I want the program to stop so I hit ctrl+c to send the process SIGINT. I have a handler registered via the python signal.signal function that catches the signal changes the value of a boolean and returns. I know the handler executes because I have a print statement at the start of the handler.
  4. At this point I would expect the main python thread to stop looping over its while loop (since the condition it checks has now been set to False by the handler) and run my cleanup code.

Step 4 only happens if the c++ thread is not running (never started or has been stopped). If the thread is running and I'm pulling things off of the sensor data queue I get a "terminate called without an active exception" and my application hangs. Other questions that mention this message point to not joining threads before exiting as the cause of the message but my code never gets to my join statement in my shutdown code.

If I had to guess, it seems like one of the driver threads or my c++ thread is exiting as soon as SIGINT is issued causing the main python thread to hang waiting for a last piece of data to be placed in the queue (right now I'm sampling the sensor at a very low rate). But I could be totally wrong about this.

Is there a reason the SIGINT signal could be stopping one of the other threads? If that's the case is there any way I can prevent this?

Thanks!

A rough outline of my code.

the main python app

import driver # this wraps a bunch of ctypes calls def sigint_handler(sig,frame): print('handling SIGINT signal') global isRun isRun = false global isRun isRun = True signal.signal(SIGINT,sigint_handler) driver.setupDriver() while isRun: data = driver.getData() logger.log(data) print('cleaning up') driver.stopDriver() #this should stop the c++ threads logger.stop() 

my driver interface layer c++

 std::queue<data_t> sensorDataQ() std::mutex dataq_mutex() std::thread worker bool isRun = True; void workerWork() { while(isRun) { auto data = getData_sensor_primary_driver(); { std::lock_guard(dataq_mutex) sensorDataQ.push(data) } } } extern "C" data_t getData() { while(sensorDataQ.empty()) { std::this_thread::sleep_for(50) //sleep for 50 miliseconds until we get some data } { std::lock_guard(dataq_mutex) sensorDataQ.push(data) } } extern "C" startDriver() { start_sensor_primary_driver() // this appears to start 4 threads according to GDB worker = std::thread(workerWork) worker.start() } extern "C" stopDriver() { isRun = false; worker.join() cleanup_primary_driver() } 
2

1 Answer

After some more digging around looks like the base driver is registering a handler for the SIGINT signal and calling exit before I have a chance to cleanup my threads.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like