summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-09-09 02:41:58 +0200
committerLennart Poettering <lennart@poettering.net>2009-09-09 02:41:58 +0200
commitc2f1994968e71f0f0a6c1f44bd8ec40edf1b6434 (patch)
tree9dcb20eb6bc23f0ca4b803aa1ea46bfb7286c9b6 /src
parent12df6860ad1103bf1e90fee4501568e45c882ee2 (diff)
udev: ratelimit device initializations
Diffstat (limited to 'src')
-rw-r--r--src/modules/module-udev-detect.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index b41b9c0f..1b1e9c1a 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -29,10 +29,13 @@
#include <sys/inotify.h>
#include <libudev.h>
+#include <pulse/timeval.h>
+
#include <pulsecore/modargs.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core-util.h>
#include <pulsecore/namereg.h>
+#include <pulsecore/ratelimit.h>
#include "module-udev-detect-symdef.h"
@@ -50,6 +53,7 @@ struct device {
char *card_name;
char *args;
uint32_t module;
+ pa_ratelimit ratelimit;
};
struct userdata {
@@ -110,6 +114,9 @@ static pa_bool_t is_card_busy(const char *id) {
pa_assert(id);
+ /* This simply uses /proc/asound/card.../pcm.../sub.../status to
+ * check whether there is still a process using this audio device. */
+
card_path = pa_sprintf_malloc("/proc/asound/card%s", id);
if (!(card_dir = opendir(card_path))) {
@@ -234,14 +241,41 @@ static void verify_access(struct userdata *u, struct device *d) {
pa_log_debug("%s is busy: %s", d->path, pa_yes_no(busy));
if (!busy) {
- pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
- m = pa_module_load(u->core, "module-alsa-card", d->args);
- if (m) {
- d->module = m->index;
- pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
+ /* So, why do we rate limit here? It's certainly ugly,
+ * but there seems to be no other way. Problem is
+ * this: if we are unable to configure/probe an audio
+ * device after opening it we will close it again and
+ * the module initialization will fail. This will then
+ * cause an inotify event on the device node which
+ * will be forwarded to us. We then try to reopen the
+ * audio device again, practically entering a busy
+ * loop.
+ *
+ * A clean fix would be if we would be able to ignore
+ * our own inotify close events. However, inotify
+ * lacks such functionality. Also, during probing of
+ * the device we cannot really distuingish between
+ * other processes causing EBUSY or ourselves, which
+ * means we have no way to figure out if the probing
+ * during opening was canceled by a "try again"
+ * failure or a "fatal" failure. */
+
+ if (pa_ratelimit_test(&d->ratelimit)) {
+ pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
+ m = pa_module_load(u->core, "module-alsa-card", d->args);
+
+ if (m) {
+ d->module = m->index;
+ pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
+ } else
+ pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
} else
- pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
+ pa_log_warn("Tried to configure %s (%s) more often than %u times in %llus",
+ d->path,
+ d->card_name,
+ d->ratelimit.burst,
+ (long long unsigned) (d->ratelimit.interval / PA_USEC_PER_SEC));
}
}
@@ -277,6 +311,7 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
d = pa_xnew0(struct device, 1);
d->path = pa_xstrdup(path);
d->module = PA_INVALID_INDEX;
+ PA_INIT_RATELIMIT(d->ratelimit, 10*PA_USEC_PER_SEC, 5);
if (!(t = udev_device_get_property_value(dev, "PULSE_NAME")))
if (!(t = udev_device_get_property_value(dev, "ID_ID")))