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 12, 2024
1 parent e50c01e commit 0174793
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions src/hotplug_libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,9 @@ static void HPRescanUsbBus(void)
}
free(driverTracker);

close(rescan_pipe[0]);
rescan_pipe[0] = -1;

Log1(PCSC_LOG_INFO, "Hotplug stopped");
pthread_exit(&retval);
}
Expand Down Expand Up @@ -531,12 +534,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)
{
Log1(PCSC_LOG_INFO, "Reload serial configuration");
Expand All @@ -546,10 +543,11 @@ static void * HPEstablishUSBNotifications(int pipefd[2])
#endif
Log1(PCSC_LOG_INFO, "End reload serial configuration");
}
close(rescan_pipe[0]);
rescan_pipe[0] = -1;
}

close(rescan_pipe[0]);
rescan_pipe[0] = -1;

return NULL;
}

Expand All @@ -567,15 +565,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 +589,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 0174793

Please sign in to comment.