mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-11 04:27:44 -05:00
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>
This commit is contained in:
parent
812e4b0c5b
commit
e1e40c2553
1 changed files with 11 additions and 20 deletions
31
src/dlmisc.c
31
src/dlmisc.c
|
|
@ -208,8 +208,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
|
||||||
{
|
{
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
struct dlobj_cache *c;
|
struct dlobj_cache *c;
|
||||||
void *func, *dlobj = NULL;
|
void *func, *dlobj;
|
||||||
int dlobj_close = 0;
|
|
||||||
|
|
||||||
snd_dlobj_lock();
|
snd_dlobj_lock();
|
||||||
list_for_each(p, &pcm_dlobj_list) {
|
list_for_each(p, &pcm_dlobj_list) {
|
||||||
|
|
@ -220,7 +219,6 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
|
||||||
continue;
|
continue;
|
||||||
if (!lib && c->lib)
|
if (!lib && c->lib)
|
||||||
continue;
|
continue;
|
||||||
dlobj = c->dlobj;
|
|
||||||
if (strcmp(c->name, name) == 0) {
|
if (strcmp(c->name, name) == 0) {
|
||||||
c->refcnt++;
|
c->refcnt++;
|
||||||
func = c->func;
|
func = c->func;
|
||||||
|
|
@ -228,17 +226,16 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dlobj = snd_dlopen(lib, RTLD_NOW);
|
||||||
if (dlobj == NULL) {
|
if (dlobj == NULL) {
|
||||||
dlobj = snd_dlopen(lib, RTLD_NOW);
|
if (verbose)
|
||||||
if (dlobj == NULL) {
|
SNDERR("Cannot open shared library %s",
|
||||||
if (verbose)
|
|
||||||
SNDERR("Cannot open shared library %s",
|
|
||||||
lib ? lib : "[builtin]");
|
lib ? lib : "[builtin]");
|
||||||
snd_dlobj_unlock();
|
snd_dlobj_unlock();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
dlobj_close = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func = snd_dlsym(dlobj, name, version);
|
func = snd_dlsym(dlobj, name, version);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
|
@ -257,8 +254,7 @@ void *snd_dlobj_cache_get(const char *lib, const char *name,
|
||||||
free((void *)c->lib);
|
free((void *)c->lib);
|
||||||
free(c);
|
free(c);
|
||||||
__err:
|
__err:
|
||||||
if (dlobj_close)
|
snd_dlclose(dlobj);
|
||||||
snd_dlclose(dlobj);
|
|
||||||
snd_dlobj_unlock();
|
snd_dlobj_unlock();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -298,16 +294,11 @@ void snd_dlobj_cache_cleanup(void)
|
||||||
struct list_head *p, *npos;
|
struct list_head *p, *npos;
|
||||||
struct dlobj_cache *c;
|
struct dlobj_cache *c;
|
||||||
|
|
||||||
/* clean up caches only when really no user is present */
|
|
||||||
snd_dlobj_lock();
|
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) {
|
list_for_each_safe(p, npos, &pcm_dlobj_list) {
|
||||||
c = list_entry(p, struct dlobj_cache, list);
|
c = list_entry(p, struct dlobj_cache, list);
|
||||||
|
if (c->refcnt)
|
||||||
|
continue;
|
||||||
list_del(p);
|
list_del(p);
|
||||||
snd_dlclose(c->dlobj);
|
snd_dlclose(c->dlobj);
|
||||||
free((void *)c->name); /* shut up gcc warning */
|
free((void *)c->name); /* shut up gcc warning */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue