Fix global (DB_PRIVATE) lock code: fix recursion counter, retry failed lock operations for up to 3 minutes. Index: lib/backend/db3.c =================================================================== --- lib/backend/db3.c.orig +++ lib/backend/db3.c @@ -586,6 +586,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; @@ -632,6 +634,10 @@ static int db3close(dbiIndex dbi, unsign rpmlog(RPMLOG_DEBUG, "closed db index %s/%s\n", dbhome, (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag))); + if (dbi->dbi_lockdbfd && + !((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) && + _lockdbfd) + _lockdbfd--; } if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) { @@ -899,8 +905,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) { @@ -1082,6 +1086,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; @@ -1091,24 +1096,40 @@ 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 && + 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); - rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), - _("cannot get %s lock on %s/%s\n"), - ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) - ? _("shared") : _("exclusive"), - dbhome, (dbfile ? dbfile : "")); - } else if (dbfile) { - rpmlog(RPMLOG_DEBUG, - "locked db index %s/%s\n", - dbhome, dbfile); + ? 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, (dbfile ? dbfile : "")); + 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, (dbfile ? dbfile : "")); + } else if (dbfile) { + rpmlog(RPMLOG_DEBUG, + "locked db index %s/%s\n", + dbhome, dbfile); + break; + } + } } + if (rc && dbi->dbi_use_dbenv) + _lockdbfd--; } } }