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);