From 93bd4c0ea689a343e416373589595a9da78d476b Mon Sep 17 00:00:00 2001 From: Philippe Houdoin Date: Sun, 20 Sep 2009 10:18:11 +0000 Subject: [PATCH] * Move initial devices scan again in a thread, to avoid deadlock. * Check that path is indeed a file, not a directory * Contrary to what BeBook say, we can't delete BLocalMidi* endpoints, but only Release() them like all others endpoints. Avoid midi_server to panic when a device is removed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33202 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/midi/DeviceWatcher.cpp | 38 +++++++++++++++++++++++++----- src/servers/midi/DeviceWatcher.h | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/servers/midi/DeviceWatcher.cpp b/src/servers/midi/DeviceWatcher.cpp index 75ac6b3382..7c3280d744 100644 --- a/src/servers/midi/DeviceWatcher.cpp +++ b/src/servers/midi/DeviceWatcher.cpp @@ -21,6 +21,7 @@ #include #include +#include #include using std::nothrow; @@ -30,6 +31,7 @@ using BPrivate::HashString; const char *kDevicesRoot = "/dev/midi"; +// const char *kDevicesRoot = "/Data/tmp"; class DeviceEndpoints { @@ -88,9 +90,17 @@ status_t DeviceWatcher::Start() { // Do an initial scan - _ScanDevices(kDevicesRoot); - // Okay, now just watch for any change + // We need to do this from a separate thread, otherwise we will deadlock. + // The reason is that we instantiate a BMidiRoster object, which sends a + // message to the midi_server to register itself, and blocks until it gets + // a response. But since we _are_ the midi_server we will never be able to + // send that response if our main thread is already blocking. + + resume_thread(spawn_thread(_InitialDevicesScanThread, + "Initial devices scan", B_NORMAL_PRIORITY, this)); + + // And watch for any change return BPathMonitor::StartWatching(kDevicesRoot, B_ENTRY_CREATED | B_ENTRY_REMOVED | B_ENTRY_MOVED | B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this); @@ -136,9 +146,20 @@ DeviceWatcher::MessageReceived(BMessage* message) // #pragma mark - +/* static */ +int32 +DeviceWatcher::_InitialDevicesScanThread(void* data) +{ + ((DeviceWatcher*) data)->_ScanDevices(kDevicesRoot); + return 0; +} + + void DeviceWatcher::_ScanDevices(const char* path) { + // printf("DeviceWatcher::_ScanDevices(\"%s\");\n", path); + BDirectory dir(path); if (dir.InitCheck() != B_OK) return; @@ -158,6 +179,13 @@ DeviceWatcher::_ScanDevices(const char* path) void DeviceWatcher::_AddDevice(const char* path) { + // printf("DeviceWatcher::_AddDevice(\"%s\");\n", path); + + BEntry entry(path); + if (! entry.IsFile()) + // Invalid path ! + return; + if ( fDeviceEndpointsMap.ContainsKey(path) ) // Already known return; @@ -166,8 +194,6 @@ DeviceWatcher::_AddDevice(const char* path) if (fd < 0) return; - // printf("DeviceWatcher::_AddDevice(\"%s\");\n", path); - MidiPortConsumer* consumer = new MidiPortConsumer(fd, path); _SetIcons(consumer); @@ -198,8 +224,8 @@ DeviceWatcher::_RemoveDevice(const char* path) deviceEndpoints->fConsumer->Unregister(); deviceEndpoints->fProducer->Unregister(); - delete deviceEndpoints->fConsumer; - delete deviceEndpoints->fProducer; + deviceEndpoints->fConsumer->Release(); + deviceEndpoints->fProducer->Release(); fDeviceEndpointsMap.Remove(path); } diff --git a/src/servers/midi/DeviceWatcher.h b/src/servers/midi/DeviceWatcher.h index 5c2e374295..838a9a5415 100644 --- a/src/servers/midi/DeviceWatcher.h +++ b/src/servers/midi/DeviceWatcher.h @@ -30,6 +30,7 @@ public: status_t Stop(); private: + static int32 _InitialDevicesScanThread(void* data); void _ScanDevices(const char* path); void _AddDevice(const char* path); void _RemoveDevice(const char* path);