Skip to main content
Skip table of contents

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:

  • SIGINT

  • SIGILL

  • SIGABRT

  • SIGFPE

  • SIGSEGV

  • SIGTERM

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:

  • SIGHUP

  • SIGINT

  • SIGQUIT

  • SIGILL

  • SIGABRT

  • SIGFPE

  • SIGBUS

  • SIGSEGV

  • SIGTERM

  • SIGTSTP

  • SIGPIPE

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:

C
...
#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");
		ljm_handler(sig);
	}
	exit(-1);
}

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.
	LJM_CloseAll();

	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);
		exit(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:

PY
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:
    pass
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.