Fix global (DB_PRIVATE) lock code: fix recursion counter, retry failed lock operations for up to 3 minutes. --- ./lib/backend/db3.c.orig 2010-03-25 14:44:42.000000000 +0000 +++ ./lib/backend/db3.c 2010-03-25 14:52:05.000000000 +0000 @@ -394,6 +394,8 @@ static int db3stat(dbiIndex dbi, unsigne return rc; } +static int _lockdbfd = 0; + static int db3close(dbiIndex dbi, unsigned int flags) { rpmdb rpmdb = dbi->dbi_rpmdb; @@ -414,6 +416,9 @@ static int db3close(dbiIndex dbi, unsign rpmlog(RPMLOG_DEBUG, "closed db index %s/%s\n", dbhome, dbi->dbi_file); + if (dbi->dbi_lockdbfd && + _lockdbfd) + _lockdbfd--; } if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) { @@ -645,8 +651,6 @@ static int db3open(rpmdb rpmdb, rpmTag r } if (rc == 0) { - static int _lockdbfd = 0; - rc = db_create(&db, dbenv, dbi->dbi_cflags); rc = cvtdberr(dbi, "db_create", rc, _debug); if (rc == 0 && db != NULL) { @@ -810,6 +814,7 @@ static int db3open(rpmdb rpmdb, rpmTag r if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { rc = 1; } else { + int tries; struct flock l; memset(&l, 0, sizeof(l)); l.l_whence = 0; @@ -819,24 +824,39 @@ static int db3open(rpmdb rpmdb, rpmTag r ? F_RDLCK : F_WRLCK; l.l_pid = 0; - rc = fcntl(fdno, F_SETLK, (void *) &l); - if (rc) { - /* Warning iff using non-private CDB locking. */ - rc = ((dbi->dbi_use_dbenv && - (dbi->dbi_eflags & DB_INIT_CDB) && - !(dbi->dbi_eflags & DB_PRIVATE)) - ? 0 : 1); - rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), - _("cannot get %s lock on %s/%s\n"), - ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) - ? _("shared") : _("exclusive"), - dbhome, dbi->dbi_file); - } else { - rpmlog(RPMLOG_DEBUG, - "locked db index %s/%s\n", - dbhome, dbi->dbi_file); + for (tries = 0; ; tries++) { + rc = fcntl(fdno, F_SETLK, (void *) &l); + if (rc) { + rc = ((dbi->dbi_use_dbenv && + (dbi->dbi_eflags & DB_INIT_CDB) && + !(dbi->dbi_eflags & DB_PRIVATE)) + ? 0 : 1); + if (errno == EAGAIN && rc) { + struct timespec ts; + if (tries == 0) + rpmlog(RPMLOG_WARNING, _("waiting for %s lock on %s/%s\n"), ((dbi->dbi_mode & (O_RDWR|O_WRONLY)) ? _("exclusive") : _("shared")), dbhome, dbi->dbi_file); + ts.tv_sec = (time_t)0; + ts.tv_nsec = 100000000; + if (tries < 10*60*3) { + nanosleep(&ts, (struct timespec *)0); + continue; + } + } + rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), + _("cannot get %s lock on %s/%s\n"), + ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) + ? _("shared") : _("exclusive"), + dbhome, dbi->dbi_file); + } else { + rpmlog(RPMLOG_DEBUG, + "locked db index %s/%s\n", + dbhome, dbi->dbi_file); + } + break; } } + if (rc && dbi->dbi_use_dbenv) + _lockdbfd--; } } }