Merge branch 'feature/increase-signal-safety'

This commit is contained in:
Tasos Sahanidis
2019-03-05 19:32:57 +02:00
5 changed files with 98 additions and 19 deletions
+4
View File
@@ -17,8 +17,10 @@
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
// Unsigned char/short definition
typedef unsigned char uchar;
@@ -67,5 +69,7 @@ void timespec_add(struct timespec* timespec, long nanoseconds);
#include "structures.h"
#define THREAD_NAME_MAX 16
#define SIGHANDLER_SENDER 0
#define SIGHANDLER_RECEIVER 1
#endif // INCLUDES_H
+53 -18
View File
@@ -11,6 +11,8 @@ extern int features_mask;
// device.c
extern int hwload_mode;
int sighandler_pipe[2] = { 0, 0 };
// Timespec utility function
void timespec_add(struct timespec* timespec, long nanoseconds){
nanoseconds += timespec->tv_nsec;
@@ -40,20 +42,56 @@ static void quit() {
usbkill();
}
void sighandler2(int type){
// Don't use ckb_warn, we want an extra \n at the beginning
printf("\n[W] Ignoring signal %d (already shutting down)\n", type);
///
/// \brief ignore_signal
/// Nested signal handler for previously received signals.
/// \param type received signal type
void ignore_signal(int type){
// Use signal-safe(7) write(3) call to print warning
write(1, "\n[W] Ignoring signal ", 22);
switch (type) {
case SIGTERM:
write(1, "SIGTERM", 7);
break;
case SIGINT:
write(1, "SIGINT", 6);
break;
case SIGQUIT:
write(1, "SIGQUIT", 7);
break;
default:
write(1, "UNKNOWN", 7);
break;
}
write(1, " (already shutting down)\n", 27);
}
void sighandler(int type){
signal(SIGTERM, sighandler2);
signal(SIGINT, sighandler2);
signal(SIGQUIT, sighandler2);
///
/// \brief exithandler
/// Main signal handler to catch further signals and call shutdown
/// sequence of daemon. This function is allowed to call unsafe
/// (signal-safe(7)) function calls, as it is itself executed in another
/// process via the socket handler.
/// \param type received signal type
void exithandler(int type){
signal(SIGTERM, ignore_signal);
signal(SIGINT, ignore_signal);
signal(SIGQUIT, ignore_signal);
printf("\n[I] Caught signal %d\n", type);
quit();
exit(0);
}
///
/// \brief signalhandler
/// Write the received signal type to the socketpair for signal-safe(7)
/// signal handling.
/// \param type received signal type
void sighandler(int type){
write(sighandler_pipe[SIGHANDLER_SENDER], &type, sizeof(int));
}
void localecase(char* dst, size_t length, const char* src){
char* ldst = dst + length;
char s;
@@ -194,17 +232,14 @@ int main(int argc, char** argv){
if(!mkdevpath(keyboard))
ckb_info("Root controller ready at %s0\n", devpath);
// Set signals
sigset_t signals;
sigfillset(&signals);
sigdelset(&signals, SIGTERM);
sigdelset(&signals, SIGINT);
sigdelset(&signals, SIGQUIT);
// Set up signal handlers for quitting the service.
sigprocmask(SIG_SETMASK, &signals, 0);
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
signal(SIGQUIT, sighandler);
// Attempt to setup signal-safe signal handlers using socketpair(2)
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sighandler_pipe) != -1){
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
signal(SIGQUIT, sighandler);
} else
ckb_warn_nofile("Unable to setup signal handlers\n");
// Start the USB system
int result = usbmain();
+5 -1
View File
@@ -217,7 +217,7 @@ const char* product_str(ushort product);
#define IS_MOUSEPAD_DEV(kb) IS_MOUSEPAD((kb)->vendor, (kb)->product)
#define USB_DELAY_DEFAULT 5
/// Start the USB main loop. Returns program exit code when finished
int usbmain();
@@ -380,4 +380,8 @@ int usb_tryreset(usbdevice* kb);
void print_urb_buffer(const char* prefix, const unsigned char* buffer, int actual_length, const char* file, int line, const char* function, int devnum);
// receive message from initial sighandler socketpair communication
extern int sighandler_pipe[2];
extern void exithandler(int type);
#endif // USB_H
+13
View File
@@ -778,6 +778,7 @@ int usbmain(){
udev_monitor_enable_receiving(monitor);
// Get an fd for the monitor
int fd = udev_monitor_get_fd(monitor);
fd_set fds;
while(udev){
FD_ZERO(&fds);
@@ -803,6 +804,18 @@ int usbmain(){
} else if(!strcmp(action, "remove"))
usb_rm_device(dev);
udev_device_unref(dev);
} else {
// if select returns -1 there is a chance that the waiting
// was interrupted by a signal
// check whether there is data available in the
// sighandler_pipe, read if there is and manually call the
// signal-handling routine
int sighandler_msg;
ioctl(sighandler_pipe[SIGHANDLER_RECEIVER], FIONREAD, &sighandler_msg);
if (sighandler_msg > 0){
read(sighandler_pipe[SIGHANDLER_RECEIVER], &sighandler_msg, sizeof(int));
exithandler(sighandler_msg);
}
}
}
udev_monitor_unref(monitor);
+23
View File
@@ -952,6 +952,17 @@ void powerEventCallback(void *refcon, io_service_t service, uint32_t type, void
}
}
///
/// \brief mac_exithandler
/// Thin layer to deconstruct the CFSocket object into a native one,
/// reading the received data from that, and passing it on to the main
/// exithandler function.
void mac_exithandler(CFSocketRef s, CFSocketCallBackType t, CFDataRef a, const void *data, void *info) {
int type;
read(CFSocketGetNative(s), &type, sizeof(int));
exithandler(type);
}
int usbmain(){
int vendor = V_CORSAIR;
@@ -1034,6 +1045,18 @@ int usbmain(){
IORegisterForSystemPower(NULL, &notify, powerEventCallback, &iterator_syspower);
CFRunLoopAddSource(mainloop, IONotificationPortGetRunLoopSource(notify), kCFRunLoopDefaultMode);
// setup signal handling via CoreFoundation socket callout mechanism
// see mac_exithandler for the reading side of this setup
CFSocketRef cf_socket = CFSocketCreateWithNative(
NULL,
sighandler_pipe[SIGHANDLER_RECEIVER],
kCFSocketReadCallBack,
mac_exithandler,
NULL);
CFRunLoopSourceRef socket_source = CFSocketCreateRunLoopSource(NULL, cf_socket, 0);
CFRunLoopAddSource(mainloop, socket_source, kCFRunLoopCommonModes);
// Enter loop to scan/connect new devices
CFRunLoopRun();
return 0;