getpwnam + getpwnam_r + LinuxThreads port = deadlock
Joshua Oreman
oremanj at webserver.get-linux.org
Fri Jul 11 22:52:38 PDT 2003
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
More information about the freebsd-hackers
mailing list