Blob Blame History Raw
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.
  *