Skip to content

Commit

Permalink
Fix shutdown race with hotplug_libusb rescan pipe
Browse files Browse the repository at this point in the history
Fix the possibility that the hotplug_libusb rescan thread remains
read()'ing from the rescan pipe throughout the daemon shutdown process.

This is possible because the |rescan_pipe| is created with some delay
after the hotplug mechanism is initialized:
HPEstablishUSBNotifications() first notifies about the initialization
via writing to |pipefd|, and only then creates |rescan_pipe|. So if
HPStopHotPluggables() is called in between, it'll end up doing nothing,
letting the hotplug thread sit infinitely long on the read() call
meanwhile the main daemon thread is shutting down.

The proposed fix is to create |rescan_pipe| in advance, so that the
shutdown logic is guaranteed to be able to write a byte to it, notifying
the background thread about the shutdown regardless of when it happens.
  • Loading branch information
emaxx-google committed Apr 13, 2024
1 parent 2b297eb commit dad51a7
Showing 1 changed file with 9 additions and 10 deletions.
19 changes: 9 additions & 10 deletions src/hotplug_libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,12 +506,6 @@ static void * HPEstablishUSBNotifications(int pipefd[2])
else
{
char dummy;

if (pipe(rescan_pipe) == -1)
{
Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
return NULL;
}
while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
{
if (AraKiriHotPlug)
Expand All @@ -523,8 +517,6 @@ static void * HPEstablishUSBNotifications(int pipefd[2])
#endif
Log1(PCSC_LOG_INFO, "End reload serial configuration");
}
close(rescan_pipe[0]);
rescan_pipe[0] = -1;
}

libusb_exit(ctx);
Expand Down Expand Up @@ -567,15 +559,22 @@ LONG HPSearchHotPluggables(const char * hpDirPath)

if (HPReadBundleValues(hpDirPath) > 0)
{
/* used for waiting for the initialization completion */
int pipefd[2];
char c;

if (pipe(pipefd) == -1)
{
Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
return -1;
}

/* used for rescan events */
if (pipe(rescan_pipe) == -1)
{
Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
return -1;
}

ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
(PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);

Expand All @@ -584,7 +583,7 @@ LONG HPSearchHotPluggables(const char * hpDirPath)
{
Log2(PCSC_LOG_ERROR, "read: %s", strerror(errno));
return -1;
};
}

/* cleanup pipe fd */
close(pipefd[0]);
Expand Down

0 comments on commit dad51a7

Please sign in to comment.