Fix global (DB_PRIVATE) lock code: fix recursion counter, retry failed lock operations for up to 3 minutes. --- ./rpmdb/db3.c.orig 2005-03-23 18:15:28.000000000 +0000 +++ ./rpmdb/db3.c 2006-01-27 20:08:29.000000000 +0000 @@ -759,6 +769,8 @@ assert(db != NULL); } /*@=mustmod@*/ +static int _lockdbfd = 0; + /*@-moduncon@*/ /* FIX: annotate db3 methods */ static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) /*@globals rpmGlobalMacroContext, h_errno, @@ -818,6 +830,10 @@ static int db3close(/*@only@*/ dbiIndex rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"), dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag))); + if (dbi->dbi_lockdbfd && + !((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) && + _lockdbfd) + _lockdbfd--; } @@ -1138,8 +1157,6 @@ static int db3open(rpmdb rpmdb, rpmTag r prDbiOpenFlags(oflags, 0), dbi->dbi_mode); if (rc == 0) { - static int _lockdbfd = 0; - /*@-moduncon@*/ /* FIX: annotate db3 methods */ rc = db_create(&db, dbenv, dbi->dbi_cflags); /*@=moduncon@*/ @@ -1356,6 +1373,7 @@ static int db3open(rpmdb rpmdb, rpmTag r if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { rc = 1; } else { + int tries; struct flock l; /*@-boundswrite@*/ memset(&l, 0, sizeof(l)); @@ -1367,24 +1385,40 @@ static int db3open(rpmdb rpmdb, rpmTag r ? F_WRLCK : F_RDLCK; 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); - rpmError( (rc ? RPMERR_FLOCK : RPMWARN_FLOCK), - _("cannot get %s lock on %s/%s\n"), - ((dbi->dbi_mode & (O_RDWR|O_WRONLY)) - ? _("exclusive") : _("shared")), - dbhome, (dbfile ? dbfile : "")); - } else if (dbfile) { - rpmMessage(RPMMESS_DEBUG, - _("locked db index %s/%s\n"), - dbhome, dbfile); + for (tries = 0; ; tries++) { + 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); + if (errno == EAGAIN && rc) { + struct timespec ts; + if (tries == 0) + rpmMessage(RPMMESS_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; + } + } + rpmError( (rc ? RPMERR_FLOCK : RPMWARN_FLOCK), + _("cannot get %s lock on %s/%s\n"), + ((dbi->dbi_mode & (O_RDWR|O_WRONLY)) + ? _("exclusive") : _("shared")), + dbhome, (dbfile ? dbfile : "")); + } else if (dbfile) { + rpmMessage(RPMMESS_DEBUG, + _("locked db index %s/%s\n"), + dbhome, dbfile); + } + break; } } + if (rc && dbi->dbi_use_dbenv) + _lockdbfd--; } } }