Suspend exclusive database lock when scriptlets get called, allowing read access in scriptlets. Only needed for DB_PRIVATE (aka global) locking. I hijacked the dbiSync function for this because I did not want to change the ABI. Index: lib/psm.c =================================================================== --- lib/psm.c.orig +++ lib/psm.c @@ -813,6 +813,8 @@ static rpmRC runScript(rpmpsm psm, Heade } if (out == NULL) return RPMRC_FAIL; /* XXX can't happen */ + rpmtsSuspendResumeDBLock(psm->ts, 0); + /*@-branchstate@*/ xx = rpmsqFork(&psm->sq); if (psm->sq.child == 0) { @@ -933,6 +935,8 @@ static rpmRC runScript(rpmpsm psm, Heade (void) psmWait(psm); + rpmtsSuspendResumeDBLock(psm->ts, 1); + /* XXX filter order dependent multilib "other" arch helper error. */ if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) { if (psm->sq.reaped < 0) { Index: lib/rpmts.c =================================================================== --- lib/rpmts.c.orig +++ lib/rpmts.c @@ -190,6 +190,11 @@ int rpmtsOpenDB(rpmts ts, int dbmode) return rc; } +int rpmtsSuspendResumeDBLock(rpmts ts, int mode) +{ + return rpmdbSuspendResumeDBLock(ts->rdb, mode); +} + int rpmtsInitDB(rpmts ts, int dbmode) { void *lock = rpmtsAcquireLock(ts); Index: lib/rpmts.h =================================================================== --- lib/rpmts.h.orig +++ lib/rpmts.h @@ -476,6 +476,10 @@ int rpmtsRebuildDB(rpmts ts) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/; +int rpmtsSuspendResumeDBLock(rpmts ts, int mode) + /*@globals fileSystem @*/ + /*@modifies fileSystem @*/; + /** \ingroup rpmts * Verify the database used by the transaction. * @param ts transaction set Index: rpmdb/db3.c =================================================================== --- rpmdb/db3.c.orig +++ rpmdb/db3.c @@ -458,6 +458,8 @@ errxit: } /*@=moduncon@*/ +static int db3SuspendResumeLock(dbiIndex dbi, int mode); + static int db3sync(dbiIndex dbi, unsigned int flags) /*@globals fileSystem @*/ /*@modifies fileSystem @*/ @@ -466,6 +468,10 @@ static int db3sync(dbiIndex dbi, unsigne int rc = 0; int _printit; + if (flags == (unsigned int)-1) + return db3SuspendResumeLock(dbi, 0); + if (flags == (unsigned int)-2) + return db3SuspendResumeLock(dbi, 1); if (db != NULL) rc = db->sync(db, flags); /* XXX DB_INCOMPLETE is returned occaisionally with multiple access. */ @@ -1412,6 +1418,50 @@ static int db3open(rpmdb rpmdb, rpmTag r /*@=nullstate =compmempass@*/ } +static int +db3SuspendResumeLock(dbiIndex dbi, int mode) +{ + struct flock l; + int rc = 0; + int tries; + int fdno = -1; + + if (!dbi->dbi_lockdbfd) + return 0; + if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) + return 0; + if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) + return 0; + if (dbi->dbi_use_dbenv && _lockdbfd == 0) + return 0; + if (!(dbi->dbi_db->fd(dbi->dbi_db, &fdno) == 0 && fdno >= 0)) + return 1; + if (mode == 0) { + memset(&l, 0, sizeof(l)); + l.l_whence = 0; + l.l_start = 0; + l.l_len = 0; + l.l_type = F_RDLCK; + rc = fcntl(fdno, F_SETLK, (void *) &l); + if (rc) + rpmMessage(RPMMESS_WARNING, _("could not suspend database lock\n")); + } else { + for (tries = 0; tries < 2; tries++) { + memset(&l, 0, sizeof(l)); + l.l_whence = 0; + l.l_start = 0; + l.l_len = 0; + l.l_type = F_WRLCK; + rc = fcntl(fdno, tries ? F_SETLKW : F_SETLK, (void *) &l); + if (!rc) + break; + if (tries == 0) + rpmMessage(RPMMESS_WARNING, _("waiting to reestablish exclusive database lock\n")); + } + } + return rc; +} + /** \ingroup db3 */ /*@-exportheadervar@*/ Index: rpmdb/rpmdb.c =================================================================== --- rpmdb/rpmdb.c.orig +++ rpmdb/rpmdb.c @@ -945,6 +945,21 @@ int rpmdbSync(rpmdb db) return rc; } +int rpmdbSuspendResumeDBLock(rpmdb db, int mode) +{ + int dbix; + int rc = 0; + if (db == NULL) return 0; + for (dbix = 0; dbix < db->db_ndbi; dbix++) { + int xx; + if (db->_dbi[dbix] == NULL) + continue; + xx = dbiSync(db->_dbi[dbix], mode ? -2 : -1); + if (xx && rc == 0) rc = xx; + } + return rc; +} + /*@-mods@*/ /* FIX: dbTemplate structure assignment */ static /*@only@*/ /*@null@*/ rpmdb newRpmdb(/*@kept@*/ /*@null@*/ const char * root,