112 lines
3.4 KiB
Diff
112 lines
3.4 KiB
Diff
|
diff -up db-5.3.28/src/env/env_region.c.pthreads db-5.3.28/src/env/env_region.c
|
||
|
--- db-5.3.28/src/env/env_region.c.pthreads 2017-06-19 08:48:19.362325045 +0200
|
||
|
+++ db-5.3.28/src/env/env_region.c 2017-06-19 08:49:38.910773653 +0200
|
||
|
@@ -305,15 +305,7 @@ user_map_functions:
|
||
|
goto creation;
|
||
|
}
|
||
|
|
||
|
- /* We have an old environment but cannot rebuild it safely. */
|
||
|
- if (ret == DB_OLD_VERSION) {
|
||
|
- __db_errx(env, DB_STR("1539",
|
||
|
- "Build signature doesn't match environment"));
|
||
|
- ret = DB_VERSION_MISMATCH;
|
||
|
- goto err;
|
||
|
- }
|
||
|
-
|
||
|
if (renv->majver != DB_VERSION_MAJOR ||
|
||
|
renv->minver != DB_VERSION_MINOR) {
|
||
|
/*
|
||
|
* Special case a region that's all nul bytes, just treat it
|
||
|
@@ -337,6 +329,20 @@ user_map_functions:
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
+ /*
|
||
|
+ * We have an old environment but cannot rebuild it safely.
|
||
|
+ * The environment might still be readable by the current process
|
||
|
+ * (only the libpthread timestamp changed) if this process is the one
|
||
|
+ * that is holding the lock on the region file as we can be sure
|
||
|
+ * the environment did not get rebuilt under our feet.
|
||
|
+ */
|
||
|
+ if (ret == DB_OLD_VERSION && __check_lock_fn(env->lockfhp->name, getpid()) ) {
|
||
|
+ __db_errx(env, DB_STR("1539",
|
||
|
+ "Build signature doesn't match environment"));
|
||
|
+ ret = DB_VERSION_MISMATCH;
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
/*
|
||
|
* Check if the environment has had a catastrophic failure.
|
||
|
*
|
||
|
diff -up db-5.3.28/src/os/os_flock.c.pthreads db-5.3.28/src/os/os_flock.c
|
||
|
--- db-5.3.28/src/os/os_flock.c.pthreads 2017-06-19 08:48:19.362325045 +0200
|
||
|
+++ db-5.3.28/src/os/os_flock.c 2017-06-19 08:48:19.364325006 +0200
|
||
|
@@ -15,6 +15,67 @@ static int __os_filelocking_notsup __P((
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
+ * __check_lock_fn --
|
||
|
+ * Parse /proc/locks to see if the file described by 'fn' is locked.
|
||
|
+ * Additionally (if 'pid' is not 0) check if the process holding
|
||
|
+ * the lock has the same pid value as 'pid'.
|
||
|
+ *
|
||
|
+ * Returns 0 if a lock on fn is found, 1 if it is not found and -1 on error.
|
||
|
+ */
|
||
|
+
|
||
|
+int __check_lock_fn(fn, pid)
|
||
|
+ char *fn;
|
||
|
+ pid_t pid;
|
||
|
+{
|
||
|
+ FILE* fp;
|
||
|
+ char buffer[PATH_MAX];
|
||
|
+ char *token;
|
||
|
+ int i, fd, inode;
|
||
|
+ struct stat st;
|
||
|
+ pid_t lpid = 0;
|
||
|
+
|
||
|
+ if (!fn)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ fp = fopen("/proc/locks", "r");
|
||
|
+ if (!fp)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ /* Get the file's inode */
|
||
|
+ if (stat(fn, &st))
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ while (fgets(buffer, sizeof(buffer), fp))
|
||
|
+ for (token = strtok(buffer, " "), i = 0; token; token = strtok(NULL, " "), i++) {
|
||
|
+ /* Do not parse any other fields */
|
||
|
+ if (i > 5)
|
||
|
+ break;
|
||
|
+ /* Save the PID */
|
||
|
+ if (i == 4)
|
||
|
+ lpid = atoi(token);
|
||
|
+ /* Check the inode */
|
||
|
+ else if (i == 5) {
|
||
|
+ inode = 0;
|
||
|
+ sscanf(token, "%*02x:%*02x:%d", &inode);
|
||
|
+ /* Not the inode we are looking for */
|
||
|
+ if (inode != st.st_ino)
|
||
|
+ continue;
|
||
|
+ /*
|
||
|
+ * We have the correct file.
|
||
|
+ * We are either looking for a specific process or we do not care at all.
|
||
|
+ */
|
||
|
+ if (!pid || lpid == pid) {
|
||
|
+ fclose(fp);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ /* Not the lock we are looking for */
|
||
|
+ }
|
||
|
+ }
|
||
|
+ fclose(fp);
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
* __os_fdlock --
|
||
|
* Acquire/release a lock on a byte in a file.
|
||
|
*
|