udev thread join fix

This commit is contained in:
Jack Andersen 2015-11-12 16:11:32 -10:00
parent c9fd0fdbb5
commit 83475b4b09
2 changed files with 41 additions and 15 deletions

View File

@ -9,7 +9,7 @@
namespace boo namespace boo
{ {
static udev* UDEV_INST = NULL; static udev* UDEV_INST = nullptr;
udev* GetUdev() udev* GetUdev()
{ {
if (!UDEV_INST) if (!UDEV_INST)
@ -22,7 +22,7 @@ class HIDListenerUdev final : public IHIDListener
DeviceFinder& m_finder; DeviceFinder& m_finder;
udev_monitor* m_udevMon; udev_monitor* m_udevMon;
std::thread* m_udevThread; std::thread m_udevThread;
bool m_udevRunning; bool m_udevRunning;
bool m_scanningEnabled; bool m_scanningEnabled;
@ -50,7 +50,7 @@ class HIDListenerUdev final : public IHIDListener
int vid = 0, pid = 0; int vid = 0, pid = 0;
udev_list_entry* attrs = udev_device_get_properties_list_entry(device); udev_list_entry* attrs = udev_device_get_properties_list_entry(device);
#if 0 #if 0
udev_list_entry* att = NULL; udev_list_entry* att = nullptr;
udev_list_entry_foreach(att, attrs) udev_list_entry_foreach(att, attrs)
{ {
const char* name = udev_list_entry_get_name(att); const char* name = udev_list_entry_get_name(att);
@ -62,18 +62,18 @@ class HIDListenerUdev final : public IHIDListener
udev_list_entry* vide = udev_list_entry_get_by_name(attrs, "ID_VENDOR_ID"); udev_list_entry* vide = udev_list_entry_get_by_name(attrs, "ID_VENDOR_ID");
if (vide) if (vide)
vid = strtol(udev_list_entry_get_value(vide), NULL, 16); vid = strtol(udev_list_entry_get_value(vide), nullptr, 16);
udev_list_entry* pide = udev_list_entry_get_by_name(attrs, "ID_MODEL_ID"); udev_list_entry* pide = udev_list_entry_get_by_name(attrs, "ID_MODEL_ID");
if (pide) if (pide)
pid = strtol(udev_list_entry_get_value(pide), NULL, 16); pid = strtol(udev_list_entry_get_value(pide), nullptr, 16);
const char* manuf = NULL; const char* manuf = nullptr;
udev_list_entry* manufe = udev_list_entry_get_by_name(attrs, "ID_VENDOR"); udev_list_entry* manufe = udev_list_entry_get_by_name(attrs, "ID_VENDOR");
if (manufe) if (manufe)
manuf = udev_list_entry_get_value(manufe); manuf = udev_list_entry_get_value(manufe);
const char* product = NULL; const char* product = nullptr;
udev_list_entry* producte = udev_list_entry_get_by_name(attrs, "ID_MODEL"); udev_list_entry* producte = udev_list_entry_get_by_name(attrs, "ID_MODEL");
if (producte) if (producte)
product = udev_list_entry_get_value(producte); product = udev_list_entry_get_value(producte);
@ -81,7 +81,7 @@ class HIDListenerUdev final : public IHIDListener
if (!listener->m_finder._insertToken(DeviceToken(type, vid, pid, manuf, product, devPath))) if (!listener->m_finder._insertToken(DeviceToken(type, vid, pid, manuf, product, devPath)))
{ {
/* Matched-insertion failed; see if generic HID interface is available */ /* Matched-insertion failed; see if generic HID interface is available */
udev_list_entry* devInterfaces = NULL; udev_list_entry* devInterfaces = nullptr;
if (type == DeviceToken::DEVTYPE_USB) if (type == DeviceToken::DEVTYPE_USB)
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_USB_INTERFACES"); devInterfaces = udev_list_entry_get_by_name(attrs, "ID_USB_INTERFACES");
else if (type == DeviceToken::DEVTYPE_BLUETOOTH) else if (type == DeviceToken::DEVTYPE_BLUETOOTH)
@ -117,8 +117,28 @@ class HIDListenerUdev final : public IHIDListener
listener->m_finder._removeToken(devPath); listener->m_finder._removeToken(devPath);
} }
/* Empty handler for SIGTERM */
static void _sigterm(int signo)
{
(void)signo;
}
static void _udevProc(HIDListenerUdev* listener) static void _udevProc(HIDListenerUdev* listener)
{ {
/* SIGTERM will be used to terminate thread */
struct sigaction s;
s.sa_handler = _sigterm;
sigemptyset(&s.sa_mask);
s.sa_flags = 0;
sigaction(SIGTERM, &s, nullptr);
/* SIGTERM will atomically become unblocked
* when pselect is entered */
sigset_t sigset, oldset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGTERM);
pthread_sigmask(SIG_BLOCK, &sigset, &oldset);
udev_monitor_enable_receiving(listener->m_udevMon); udev_monitor_enable_receiving(listener->m_udevMon);
int fd = udev_monitor_get_fd(listener->m_udevMon); int fd = udev_monitor_get_fd(listener->m_udevMon);
while (listener->m_udevRunning) while (listener->m_udevRunning)
@ -126,7 +146,12 @@ class HIDListenerUdev final : public IHIDListener
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(fd, &fds); FD_SET(fd, &fds);
select(fd+1, &fds, NULL, NULL, NULL); if (pselect(fd+1, &fds, nullptr, nullptr, nullptr, &oldset) < 0)
{
/* SIGTERM handled here */
if (errno == EINTR)
break;
}
udev_device* dev = udev_monitor_receive_device(listener->m_udevMon); udev_device* dev = udev_monitor_receive_device(listener->m_udevMon);
if (dev) if (dev)
{ {
@ -144,7 +169,6 @@ public:
HIDListenerUdev(DeviceFinder& finder) HIDListenerUdev(DeviceFinder& finder)
: m_finder(finder) : m_finder(finder)
{ {
/* Setup hotplug events */ /* Setup hotplug events */
m_udevMon = udev_monitor_new_from_netlink(GetUdev(), "udev"); m_udevMon = udev_monitor_new_from_netlink(GetUdev(), "udev");
if (!m_udevMon) if (!m_udevMon)
@ -163,16 +187,14 @@ public:
/* Start hotplug thread */ /* Start hotplug thread */
m_udevRunning = true; m_udevRunning = true;
m_udevThread = new std::thread(_udevProc, this); m_udevThread = std::thread(_udevProc, this);
} }
~HIDListenerUdev() ~HIDListenerUdev()
{ {
m_udevRunning = false; m_udevRunning = false;
pthread_kill(m_udevThread->native_handle(), SIGINT); pthread_kill(m_udevThread.native_handle(), SIGTERM);
m_udevThread->join(); m_udevThread.join();
delete m_udevThread;
udev_monitor_unref(m_udevMon); udev_monitor_unref(m_udevMon);
} }

View File

@ -341,6 +341,7 @@ public:
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory()
{ {
XLockDisplay(m_xDisp);
if (!m_loadCtx) if (!m_loadCtx)
{ {
m_loadCtx = glXCreateContextAttribsARB(m_xDisp, m_fbconfig, m_glxCtx, True, ContextAttribs); m_loadCtx = glXCreateContextAttribsARB(m_xDisp, m_fbconfig, m_glxCtx, True, ContextAttribs);
@ -349,6 +350,7 @@ public:
} }
if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_loadCtx)) if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_loadCtx))
Log.report(LogVisor::FatalError, "unable to make load GLX context current"); Log.report(LogVisor::FatalError, "unable to make load GLX context current");
XUnlockDisplay(m_xDisp);
return getDataFactory(); return getDataFactory();
} }
@ -362,8 +364,10 @@ public:
{ {
if (m_timerBound) if (m_timerBound)
return; return;
XLockDisplay(m_xDisp);
if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_timerCtx)) if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_timerCtx))
Log.report(LogVisor::FatalError, "unable to make timer GLX context current"); Log.report(LogVisor::FatalError, "unable to make timer GLX context current");
XUnlockDisplay(m_xDisp);
m_timerBound = true; m_timerBound = true;
} }