summaryrefslogtreecommitdiff
path: root/extra/alsa-lib/alsa-lib-1.0.27-segfault.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extra/alsa-lib/alsa-lib-1.0.27-segfault.patch')
-rw-r--r--extra/alsa-lib/alsa-lib-1.0.27-segfault.patch102
1 files changed, 102 insertions, 0 deletions
diff --git a/extra/alsa-lib/alsa-lib-1.0.27-segfault.patch b/extra/alsa-lib/alsa-lib-1.0.27-segfault.patch
new file mode 100644
index 000000000..72df46185
--- /dev/null
+++ b/extra/alsa-lib/alsa-lib-1.0.27-segfault.patch
@@ -0,0 +1,102 @@
+From e1e40c25535af35fa5cdf7ffc95a01fbff098ddd Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 15 Apr 2013 18:12:17 +0200
+Subject: [PATCH] Fix doubly call of dlclose() in dlobj caching code
+
+When multiple dlobj_cache items point to the same dlobj, dlclose() may
+be called wrongly multiple times when these items are cleared, because
+we manage the dlobj_cache list as a flat list. This results in a bad
+segfault we've seen in openal-soft, for example.
+
+For fixing this, we need the refcounting of dlobj itself. But, in
+this case, we don't have to manage yet another list, since dlopen()
+does a proper refcounting by itself. That is, we can just call always
+dlopen() at each time a new function is assigned, and also call
+dlclose() for each released dlobj_cache item at cleanup.
+
+Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=814250
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ src/dlmisc.c | 31 +++++++++++--------------------
+ 1 file changed, 11 insertions(+), 20 deletions(-)
+
+diff --git a/src/dlmisc.c b/src/dlmisc.c
+index 3788382..2de0234 100644
+--- a/src/dlmisc.c
++++ b/src/dlmisc.c
+@@ -208,8 +208,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
+ {
+ struct list_head *p;
+ struct dlobj_cache *c;
+- void *func, *dlobj = NULL;
+- int dlobj_close = 0;
++ void *func, *dlobj;
+
+ snd_dlobj_lock();
+ list_for_each(p, &pcm_dlobj_list) {
+@@ -220,7 +219,6 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
+ continue;
+ if (!lib && c->lib)
+ continue;
+- dlobj = c->dlobj;
+ if (strcmp(c->name, name) == 0) {
+ c->refcnt++;
+ func = c->func;
+@@ -228,17 +226,16 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
+ return func;
+ }
+ }
++
++ dlobj = snd_dlopen(lib, RTLD_NOW);
+ if (dlobj == NULL) {
+- dlobj = snd_dlopen(lib, RTLD_NOW);
+- if (dlobj == NULL) {
+- if (verbose)
+- SNDERR("Cannot open shared library %s",
++ if (verbose)
++ SNDERR("Cannot open shared library %s",
+ lib ? lib : "[builtin]");
+- snd_dlobj_unlock();
+- return NULL;
+- }
+- dlobj_close = 1;
++ snd_dlobj_unlock();
++ return NULL;
+ }
++
+ func = snd_dlsym(dlobj, name, version);
+ if (func == NULL) {
+ if (verbose)
+@@ -257,8 +254,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
+ free((void *)c->lib);
+ free(c);
+ __err:
+- if (dlobj_close)
+- snd_dlclose(dlobj);
++ snd_dlclose(dlobj);
+ snd_dlobj_unlock();
+ return NULL;
+ }
+@@ -298,16 +294,11 @@ void snd_dlobj_cache_cleanup(void)
+ struct list_head *p, *npos;
+ struct dlobj_cache *c;
+
+- /* clean up caches only when really no user is present */
+ snd_dlobj_lock();
+- list_for_each(p, &pcm_dlobj_list) {
+- c = list_entry(p, struct dlobj_cache, list);
+- if (c->refcnt)
+- goto unlock;
+- }
+-
+ list_for_each_safe(p, npos, &pcm_dlobj_list) {
+ c = list_entry(p, struct dlobj_cache, list);
++ if (c->refcnt)
++ continue;
+ list_del(p);
+ snd_dlclose(c->dlobj);
+ free((void *)c->name); /* shut up gcc warning */
+--
+1.7.11.7
+