5.1 - Does LJM handle signals? | LabJack
« Close

Datasheets and User Guides

App Notes

Software & Driver


5.1 - Does LJM handle signals?

Does LJM handle signals?

LJM catches all terminal signals, by default, in order to clean up LabJack device connections. LJM's signal handlers do the following:

  • Ends all device streaming and close all device connections
  • Optionally log which signal was received at LJM_FATAL priority
  • Essentially exit the processes by setting the signal handler to default and re-raising the signal

LJM attempts to set the signal handlers upon the first call to LJM that attempts communication. (LJM_CloseAll is a quick way to force LJM to initialize the signal handlers.)

On Windows, signals are handled using signal. The signals that are handled are:


On Linux/macOS, LJM uses the oldact parameter of sigaction to determine if there was previously a signal handler; if oldact is not NULL for a given signal, LJM will reset oldact as the signal handler and not handle that signal. The default signals that are handled are:


Custom Cleanup on Linux/macOS: If your application needs to clean up resources, you can call LJM's signal handler from your own signal handler. To do this, force LJM to initialize signal handlers by calling LJM_CloseAll, then call sigaction to set your handler, and finally set the previous signal handler to be called in your handler. A Linux/macOS C++ example to catch Ctrl-C follows:

#include <signal.h>
#include <errno.h>

static volatile void (*ljm_handler)(int) = NULL;

static int handleToCleanUp = 0;

void my_handler(int sig)
	// printf may not be re-entrant: because of this, it typically should not be
	// used in a signal handler. It is used here for ease of exposition.
	printf("my_handler is handling signal: %d\n", sig);

	// Perform custom cleanup behavior here
	int err = LJM_eWriteName(handleToCleanUp, ...);
	if (err) {
		// Handle error

	if (ljm_handler != NULL) {
		printf("Calling ljm_handler from my_handler...\n");

int main()
	// Initialize the LJM signal handler by "attempting" device communication
	// using LJM_CloseAll - we can ignore the return value. Other functions,
	// such as LJM_Open or LJM_ListAll work as well.

	struct sigaction act, oldact;
	act.sa_handler = my_handler;
	act.sa_flags = 0;
	int error = sigaction(SIGINT, &act, &oldact);
	if (error) {
		printf("There was an error during sigaction: %d\n", errno);

	printf("oldact.sa_handler: %p\n", oldact.sa_handler);
	ljm_handler = (volatile void (*)(int))oldact.sa_handler;
	int handle;
	error = LJM_Open(LJM_dtANY, LJM_ctANY, LJM_idANY, &handle);
	if (error) {
		// Handle error
	handleToCleanUp = handle;


Note that sigprocmask can be used to block signals while you are calling sigaction. Also note that other signal behaviors can be implemented using sigaction. See the man-pages for sigaction and sigprocmask for more details.

Custom Cleanup for ctrl+c on Windows: If your application needs to clean up resources, you can use SetConsoleCtrlHandler to add a handler routine. Do this after LJM's signal handlers are initialized. When ctrl+c is pressed, your handler routine is called, then LJM's signal handler is called, which exits the program.

A minimal Python script to set up a handler routine by importing Kernel32.dll is as follows:

import ctypes
import sys

from labjack import ljm
ljm.closeAll() # Initializes LJM's signal handlers

if not sys.platform.startswith("win32"):
    raise ValueError("Unsupported platform: " + sys.platform)
kernel32 = ctypes.CDLL("Kernel32.dll")

def ctrlc_handler(dwCtrlType):
    print("Python ctrlc_handler called with dwCtrlType " + str(dwCtrlType))
    # This is where you would close a file, etc.

ctrlc_callback_type = ctypes.WINFUNCTYPE(None, ctypes.c_int)
cc_h = ctrlc_callback_type(ctrlc_handler)
success = kernel32.SetConsoleCtrlHandler(cc_h, True)
if not success:
    ValueError("SetConsoleCtrlHandler failed")

print "please press ctrl+c..."
while True: