]> git.sesse.net Git - nageru/blobdiff - alsa_pool.cpp
Shut down the ALSA probe retry threads cleanly on exit.
[nageru] / alsa_pool.cpp
index 28e7ee08829e42218a9dbe63153403ddd62486d0..5983446e37ab4f687cfaa7a9e4db11d497eff711 100644 (file)
@@ -27,6 +27,12 @@ ALSAPool::~ALSAPool()
                        device.input->stop_capture_thread();
                }
        }
+       should_quit = true;
+       inotify_thread.join();
+
+       while (retry_threads_running > 0) {
+               this_thread::sleep_for(std::chrono::milliseconds(100));
+       }
 }
 
 std::vector<ALSAPool::Device> ALSAPool::get_devices()
@@ -102,6 +108,7 @@ void ALSAPool::probe_device_with_retry(unsigned card_index, unsigned dev_index)
        // then start it ourselves.
        fprintf(stderr, "Trying %s again in one second...\n", address);
        add_device_tries_left[address] = num_retries;
+       ++retry_threads_running;
        thread(&ALSAPool::probe_device_retry_thread_func, this, card_index, dev_index).detach();
 }
 
@@ -115,11 +122,12 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_
 
                // See if there are any retries left.
                lock_guard<mutex> lock(add_device_mutex);
-               if (!add_device_tries_left.count(address) ||
+               if (should_quit ||
+                   !add_device_tries_left.count(address) ||
                    add_device_tries_left[address] == 0) {
                        add_device_tries_left.erase(address);
                        fprintf(stderr, "Giving up probe of %s.\n", address);
-                       return;
+                       break;
                }
 
                // Seemingly there were. Give it a try (we still hold the mutex).
@@ -127,11 +135,11 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_
                if (result == ProbeResult::SUCCESS) {
                        add_device_tries_left.erase(address);
                        fprintf(stderr, "Probe of %s succeeded.\n", address);
-                       return;
+                       break;
                } else if (result == ProbeResult::FAILURE || --add_device_tries_left[address] == 0) {
                        add_device_tries_left.erase(address);
                        fprintf(stderr, "Giving up probe of %s.\n", address);
-                       return;
+                       break;
                }
 
                // Failed again.
@@ -139,6 +147,8 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_
                fprintf(stderr, "Trying %s again in one second (%d tries left)...\n",
                        address, add_device_tries_left[address]);
        }
+
+       --retry_threads_running;
 }
 
 ALSAPool::ProbeResult ALSAPool::probe_device_once(unsigned card_index, unsigned dev_index)
@@ -255,7 +265,7 @@ void ALSAPool::unplug_device(unsigned card_index, unsigned dev_index)
 
 void ALSAPool::init()
 {
-       thread(&ALSAPool::inotify_thread_func, this).detach();
+       inotify_thread = thread(&ALSAPool::inotify_thread_func, this);
        enumerate_devices();
 }
 
@@ -278,8 +288,36 @@ void ALSAPool::inotify_thread_func()
 
        int size = sizeof(inotify_event) + NAME_MAX + 1;
        unique_ptr<char[]> buf(new char[size]);
-       for ( ;; ) {
-               int ret = read(inotify_fd, buf.get(), size);
+       while (!should_quit) {
+               pollfd fds;
+               fds.fd = inotify_fd;
+               fds.events = POLLIN;
+               fds.revents = 0;
+
+               int ret = poll(&fds, 1, 100);
+               if (ret == -1) {
+                       if (errno == EINTR) {
+                               continue;
+                       } else {
+                               perror("poll(inotify_fd)");
+                               return;
+                       }
+               }
+               if (ret == 0) {
+                       continue;
+               }
+
+               ret = read(inotify_fd, buf.get(), size);
+               if (ret == -1) {
+                       if (errno == EINTR) {
+                               continue;
+                       } else {
+                               perror("read(inotify_fd)");
+                               close(watch_fd);
+                               close(inotify_fd);
+                               return;
+                       }
+               }
                if (ret < int(sizeof(inotify_event))) {
                        fprintf(stderr, "inotify read unexpectedly returned %d, giving up hotplug of ALSA devices.\n",
                                int(ret));
@@ -310,6 +348,8 @@ void ALSAPool::inotify_thread_func()
                        }
                }
        }
+       close(watch_fd);
+       close(inotify_fd);
 }
 
 void ALSAPool::reset_device(unsigned index)