diff -up db-5.3.28/src/env/env_region.c.rpmchk db-5.3.28/src/env/env_region.c --- db-5.3.28/src/env/env_region.c.rpmchk 2017-06-01 12:09:49.191891965 +0200 +++ db-5.3.28/src/env/env_region.c 2017-06-01 12:09:49.193891929 +0200 @@ -289,7 +289,8 @@ user_map_functions: if (create_ok && __env_check_recreate(env, renv, signature) == DB_OLD_VERSION && - (ret = ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1)) == 0) { + (ret = ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1)) == 0 && + (ret = __rpm_lock_check(env)) == 0 ) { if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) __db_msg(env, "Recreating idle environment"); F_SET(infop, REGION_CREATE_OK); diff -up db-5.3.28/src/os/os_flock.c.rpmchk db-5.3.28/src/os/os_flock.c --- db-5.3.28/src/os/os_flock.c.rpmchk 2017-06-01 12:09:49.191891965 +0200 +++ db-5.3.28/src/os/os_flock.c 2017-06-01 12:16:28.309175645 +0200 @@ -15,6 +15,53 @@ static int __os_filelocking_notsup __P(( #endif /* + * __rpm_lock_check -- + * Try to acquire and release a lock used by rpm to see + * if libdb is being updated and it is safe to access + * its environment files. + * + * FIXME: This function leaks the file descriptor on purpose + * so that rpm's transaction lock is not dropped due to + * how fcntl locks interact with close(2). + */ + +#define RPM_PATH SHAREDSTATEDIR "/rpm" +#define RPMLOCK_PATH RPM_PATH "/.rpm.lock" + +int __rpm_lock_check(env) + ENV *env; +{ +#ifdef HAVE_FCNTL + struct flock info; + int fd; + int ret; + + if (strstr(env->db_home, RPM_PATH) == NULL) + /* No need to check the transaction lock if not in rpm */ + return 0; + + fd = open(RPMLOCK_PATH, O_RDWR); + if (fd == -1) + return 1; + /* Try to get an exclusive lock on rpm's lock file */ + info.l_type = F_WRLCK; + info.l_whence = SEEK_SET; + info.l_start = 0; + info.l_len = 0; + info.l_pid = 0; + /* We do not want to hold so just check if we can get it */ + if ((ret = fcntl(fd, F_GETLK, &info)) != -1 && info.l_type == F_UNLCK) + /* Lock is not taken, the environment can be rebuilt */ + return 0; + else + return 1; +#else + /* fcntl not supported, fail with error message */ + return __os_filelocking_notsup(env); +#endif +} + +/* * __os_fdlock -- * Acquire/release a lock on a byte in a file. *