Date: Fri, 11 Jul 2003 22:52:48 -0700 From: Joshua Oreman <oremanj@webserver.get-linux.org> To: freebsd-hackers@freebsd.org Subject: getpwnam + getpwnam_r + LinuxThreads port = deadlock Message-ID: <20030712055248.GA23189@webserver.get-linux.org>
next in thread | raw e-mail | index | archive | help
Hi -hackers, System: FreeBSD 5.0-CURRENT cvsupped around 5.0-RELEASE I'm writing an app that links with the LinuxThreads (/usr/ports/devel/linuxthreads) and also uses getpwnam(). The problem: a deadlock. GDB backtrace: (gdb) bt #0 0x28140053 in sigsuspend () from /usr/lib/libc.so.5 #1 0x28090428 in __pthread_wait_for_restart_signal () from /usr/local/lib/liblthread.so.3 #2 0x28090548 in __pthread_suspend_old () from /usr/local/lib/liblthread.so.3 #3 0x2808d5fc in __pthread_alt_lock () from /usr/local/lib/liblthread.so.3 #4 0x28090df0 in pthread_mutex_lock () from /usr/local/lib/liblthread.so.3 #5 0x2808595b in getpwnam_r () from /usr/local/lib/liblthread.so.3 #6 0x2815405b in getpwuid_r () from /usr/lib/libc.so.5 #7 0x28153fab in getpwuid_r () from /usr/lib/libc.so.5 #8 0x28154129 in getpwnam () from /usr/lib/libc.so.5 #9 0x28085966 in getpwnam_r () from /usr/local/lib/liblthread.so.3 #10 0x2815405b in getpwuid_r () from /usr/lib/libc.so.5 #11 0x28153fab in getpwuid_r () from /usr/lib/libc.so.5 #12 0x28154129 in getpwnam () from /usr/lib/libc.so.5 #13 0x080495ca in check_pwinfo (username=0x155 <Error reading address 0x155: Bad address>, passwd=0x155 <Error reading address 0x155: Bad address>, group=0xbfbfeed8) #14 0x0804a212 in handle_connection (tb=0xbfbff988) #15 0x0804a52b in main (argc=4, argv=0xbfbff9f8) #16 0x080494f5 in _start () (gdb) f 13 #13 0x080495ca in check_pwinfo (username=0x155 <Error reading address 0x155: Bad address>, passwd=0x155 <Error reading address 0x155: Bad address>, group=0xbfbfeed8) 43 pw = getpwnam (username); Basically: FreeBSD implements getpwnam() as a wrapper around getpwnam_r(), as seen in src/lib/libc/gen/getpwent.c: struct passwd * getpwnam(const char *name) { union key key; key.name = name; return (getpw(wrap_getpwnam_r, key)); } While LinuxThreads does the opposite, basically using getpwnam() + mutex to make getpwnam_r, as seen in ports/devel/linuxthreads/work/linuxthreads-2.2.3_11/getpw_r.c: int getpwnam_r (const char *name, struct passwd *result, char *buffer, size_t buflen, struct passwd ** resptr) { struct passwd * p; int retval; pthread_mutex_lock (&getpw_mutex); p = getpwnam (name); if (p == NULL) { *resptr = NULL; retval = ESRCH; } else if (convert (p, result, buffer, buflen) != 0) { *resptr = NULL; retval = ERANGE; } else { *resptr = result; retval = 0; } pthread_mutex_unlock (&getpw_mutex); return retval; } So basically, my app calls getpwnam(), which calls the overridden getpwnam_r() from LinuxThreads, which calls getpwnam() from libc again, and then calls getpwnam_r() from LinuxThreads again, and deadlocks trying to recursively lock its own mutex. Obviously, if there was no mutex the stack would leak out the back of my computer :-) Any ideas here? -- Josh
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030712055248.GA23189>