Re: Follow-up: Re: recent update breaks some ports

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Wed, 11 Apr 2012 22:42:39 +0300
On Thu, Apr 12, 2012 at 04:04:11AM +0900, Taku YAMAMOTO wrote:
> The following is the first occurence of wlock-within-wlock incident
> when I run xfdesktop-settings under gdb.
> 
> Hardware watchpoint 3: lock_place[0].count_ww
> 
> Old value = 0
> New value = 1
> 0x28f52522 in _thr_rtld_wlock_acquire (lock=0x28f63600)
>     at /usr/src/lib/libthr/thread/thr_rtld.c:152
> 152             HANDLE_NESTED_ACQ(count_ww);
> (gdb) bt
> #0  0x28f52522 in _thr_rtld_wlock_acquire (lock=0x28f63600)
>     at /usr/src/lib/libthr/thread/thr_rtld.c:152
> #1  0x280719c1 in wlock_acquire () from /libexec/ld-elf.so.1
> #2  0x2806eb15 in dlopen_object () from /libexec/ld-elf.so.1
> #3  0x2806ef1b in load_filtee1 () from /libexec/ld-elf.so.1
> #4  0x2806ef7d in load_filtees () from /libexec/ld-elf.so.1
> #5  0x2806f318 in symlook_obj () from /libexec/ld-elf.so.1
> #6  0x2806f421 in symlook_list () from /libexec/ld-elf.so.1
> #7  0x2806fa0b in symlook_default () from /libexec/ld-elf.so.1
> #8  0x2806fc1a in find_symdef () from /libexec/ld-elf.so.1
> #9  0x2806a426 in reloc_non_plt () from /libexec/ld-elf.so.1
> #10 0x2806d453 in relocate_objects () from /libexec/ld-elf.so.1
> #11 0x2806ee6d in dlopen_object () from /libexec/ld-elf.so.1
> #12 0x2806f862 in rtld_dlopen () from /libexec/ld-elf.so.1
> #13 0x28d2a6b0 in g_module_open () from /usr/local/lib/libgmodule-2.0.so.0
> #14 0x28406894 in gtk_im_context_simple_new ()
>    from /usr/local/lib/libgtk-x11-2.0.so.0
Thank you for the report, I hope that the patch at the end of the message
would take care of this problem.

> 
> 
> The following is the first occurence of rlock-within-wlock incident.
> 
> Hardware watchpoint 2: lock_place[0].count_rw
> 
> Old value = 0
> New value = 1
> 0x28f526fd in _thr_rtld_rlock_acquire (lock=0x28f63600)
>     at /usr/src/lib/libthr/thread/thr_rtld.c:133
> 133             HANDLE_NESTED_ACQ(count_rw);
> (gdb) bt
> #0  0x28f526fd in _thr_rtld_rlock_acquire (lock=0x28f63600)
>     at /usr/src/lib/libthr/thread/thr_rtld.c:133
> #1  0x28071291 in rlock_acquire () from /libexec/ld-elf.so.1
> #2  0x2806fccb in _rtld_bind () from /libexec/ld-elf.so.1
> #3  0x28069dc9 in _rtld_bind_start () from /libexec/ld-elf.so.1
> #4  0x290c3000 in ?? ()
> #5  0x00000148 in ?? ()
> #6  0x29356318 in ?? () from /usr/lib/libsupc++.so.1
> #7  0x28f503e0 in _thr_once_init ()
>    from /home/taku/work/build/biotite/usr/src/lib/libthr/libthr.so.3
> #8  0xffffffff in ?? ()
> #9  0x00200202 in ?? ()
> #10 0x290c3000 in ?? ()
> #11 0x00000148 in ?? ()
> #12 0x2935eae0 in __gxx_personality_v0 () from /usr/lib/libsupc++.so.1
> #13 0x2935f5c5 in __cxa_get_globals () from /usr/lib/libsupc++.so.1
> #14 0x290c2710 in ?? ()
> #15 0xbfbfdc48 in ?? ()
> #16 0x29356325 in ?? () from /usr/lib/libsupc++.so.1
> #17 0x280714c9 in lock_release () from /libexec/ld-elf.so.1
> Previous frame inner to this frame (corrupt stack?)
Unortunately, this trace is not usefule, it seems that you need
to recompile rtld/libc/libthr with debugging symbols to get the issue
fixed.

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index f02d276..1def854 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
_at__at_ -85,7 +85,7 _at__at_ static void digest_dynamic(Obj_Entry *, int);
 static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
 static Obj_Entry *dlcheck(void *);
 static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj,
-    int lo_flags, int mode);
+    int lo_flags, int mode, RtldLockState *lockstate);
 static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int);
 static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
 static bool donelist_check(DoneList *, const Obj_Entry *);
_at__at_ -1672,13 +1672,14 _at__at_ unload_filtees(Obj_Entry *obj)
 }
 
 static void
-load_filtee1(Obj_Entry *obj, Needed_Entry *needed, int flags)
+load_filtee1(Obj_Entry *obj, Needed_Entry *needed, int flags,
+    RtldLockState *lockstate)
 {
 
     for (; needed != NULL; needed = needed->next) {
 	needed->obj = dlopen_object(obj->strtab + needed->name, -1, obj,
 	  flags, ((ld_loadfltr || obj->z_loadfltr) ? RTLD_NOW : RTLD_LAZY) |
-	  RTLD_LOCAL);
+	  RTLD_LOCAL, lockstate);
     }
 }
 
_at__at_ -1688,8 +1689,8 _at__at_ load_filtees(Obj_Entry *obj, int flags, RtldLockState *lockstate)
 
     lock_restart_for_upgrade(lockstate);
     if (!obj->filtees_loaded) {
-	load_filtee1(obj, obj->needed_filtees, flags);
-	load_filtee1(obj, obj->needed_aux_filtees, flags);
+	load_filtee1(obj, obj->needed_filtees, flags, lockstate);
+	load_filtee1(obj, obj->needed_aux_filtees, flags, lockstate);
 	obj->filtees_loaded = true;
     }
 }
_at__at_ -2489,7 +2490,7 _at__at_ rtld_dlopen(const char *name, int fd, int mode)
 	    lo_flags |= RTLD_LO_TRACE;
 
     return (dlopen_object(name, fd, obj_main, lo_flags,
-      mode & (RTLD_MODEMASK | RTLD_GLOBAL)));
+      mode & (RTLD_MODEMASK | RTLD_GLOBAL), NULL));
 }
 
 static void
_at__at_ -2504,17 +2505,20 _at__at_ dlopen_cleanup(Obj_Entry *obj)
 
 static Obj_Entry *
 dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
-    int mode)
+    int mode, RtldLockState *lockstate)
 {
     Obj_Entry **old_obj_tail;
     Obj_Entry *obj;
     Objlist initlist;
-    RtldLockState lockstate;
+    RtldLockState mlockstate;
     int result;
 
     objlist_init(&initlist);
 
-    wlock_acquire(rtld_bind_lock, &lockstate);
+    if (lockstate == NULL && !(lo_flags & RTLD_LO_EARLY)) {
+	wlock_acquire(rtld_bind_lock, &mlockstate);
+	lockstate = &mlockstate;
+    }
     GDB_STATE(RT_ADD,NULL);
 
     old_obj_tail = obj_tail;
_at__at_ -2543,7 +2547,7 _at__at_ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
 	    if (result == -1 || (relocate_objects(obj,
 	     (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld,
 	      (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0,
-	      &lockstate)) == -1) {
+	      lockstate)) == -1) {
 		dlopen_cleanup(obj);
 		obj = NULL;
 	    } else if (lo_flags & RTLD_LO_EARLY) {
_at__at_ -2587,28 +2591,31 _at__at_ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
     GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL);
 
     if (!(lo_flags & RTLD_LO_EARLY)) {
-	map_stacks_exec(&lockstate);
+	map_stacks_exec(lockstate);
     }
 
     if (initlist_objects_ifunc(&initlist, (mode & RTLD_MODEMASK) == RTLD_NOW,
       (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0,
-      &lockstate) == -1) {
+      lockstate) == -1) {
 	objlist_clear(&initlist);
 	dlopen_cleanup(obj);
-	lock_release(rtld_bind_lock, &lockstate);
+	if (lockstate == &mlockstate)
+	    lock_release(rtld_bind_lock, lockstate);
 	return (NULL);
     }
 
     if (!(lo_flags & RTLD_LO_EARLY)) {
 	/* Call the init functions. */
-	objlist_call_init(&initlist, &lockstate);
+	objlist_call_init(&initlist, lockstate);
     }
     objlist_clear(&initlist);
-    lock_release(rtld_bind_lock, &lockstate);
+    if (lockstate == &mlockstate)
+	lock_release(rtld_bind_lock, lockstate);
     return obj;
 trace:
     trace_loaded_objects(obj);
-    lock_release(rtld_bind_lock, &lockstate);
+    if (lockstate == &mlockstate)
+	lock_release(rtld_bind_lock, lockstate);
     exit(0);
 }
 

Received on Wed Apr 11 2012 - 17:42:47 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:25 UTC