Hi, unfortunately, Christian's patch (using PQconnectdb instead of PQsetdbLogin) does not work / suffice for libpq4.
Without a running nscd, PQconnectdb attempts to setup the SSL environment and searches for $HOME/.postgresql/server.crt (or similar), calling getpwuid to retrieve the home-directory. This obviously causes another entrance into libnss-pgsql which results in a hang while waiting for the (already owned) lock. While running nscd, the second nss call (getpwuid) can be resolved via /etc/passwd (as long as nscd runs as root / a local user) and therefore avoids the dead-lock. The attached patch replaces all pthread_mutex_lock() calls with pthread_mutex_trylock(), aborting any recursive locking attempts with NSS_STATUS_UNAVAIL. Not very pretty, but appears to work fine. (Might need more testing though.) Fabian ii libnss-pgsql1 1.3.1 ii libc6 2.3.6.ds1-10 ii libpq4 8.1.6-1
diff -urN libnss-pgsql-1.3.1/src/interface.c libnss-pgsql-1.3.1.fixed/src/interface.c --- libnss-pgsql-1.3.1/src/interface.c 2006-04-16 17:04:46.000000000 +0200 +++ libnss-pgsql-1.3.1.fixed/src/interface.c 2007-01-15 22:29:26.000000000 +0100 @@ -23,7 +23,9 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } if(!backend_isopen()) { backend_open(); } @@ -38,7 +40,9 @@ enum nss_status _nss_pgsql_endpwent(void) { - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return NSS_STATUS_UNAVAIL; + } backend_close(); pthread_mutex_unlock(&lock); @@ -53,7 +57,9 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } // Make sure the database is opened in case no one has called setpwent() if(!backend_isopen()) @@ -76,7 +82,10 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } + if(backend_open()) { retval = backend_getpwnam(pwnam, result, buffer, buflen, errnop); backend_close(); @@ -95,7 +104,10 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } + if(backend_open()) { retval = backend_getpwuid(uid, result, buffer, buflen, errnop); backend_close(); @@ -113,7 +125,9 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } if(!backend_isopen()) { backend_open(); } @@ -129,7 +143,9 @@ enum nss_status _nss_pgsql_endgrent(void) { - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return NSS_STATUS_UNAVAIL; + } backend_close(); pthread_mutex_unlock(&lock); @@ -144,7 +160,9 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } // Make sure the database is opened in case no one has called setpwent() if(!backend_isopen()) @@ -167,7 +185,9 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } if(backend_open()) { retval = backend_getgrnam(grnam, result, buffer, buflen, errnop); backend_close(); @@ -186,7 +206,9 @@ { enum nss_status retval = NSS_STATUS_UNAVAIL; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } if(backend_open()) { retval = backend_getgrgid(gid, result, buffer, buflen, errnop); backend_close(); @@ -208,7 +230,9 @@ enum nss_status retval = NSS_STATUS_UNAVAIL; size_t numgroups; - pthread_mutex_lock(&lock); + if (pthread_mutex_trylock(&lock) != 0) { + return retval; + } if(backend_open()) { numgroups = backend_initgroups_dyn(user, group, start, size, groupsp, limit, errnop);