[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#8350) lmdb SIGBUS error on full partition and possible double free issue



Full_Name: Jeremiah Morrill
Version: 0.9
OS: Linux (Ubuntu14)
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (70.173.183.164)


Two possible issues.  Semi-related.

The first:
On a full storage partition, when creating a new database, I get a SIGBUS.  I
believe it is caused by the locks successfully mmap()ing, but not really having
the storage to back it.  I hacked in a "posix_fallocate" to make sure the
storage space is there and it appeared to fix it.  I have no idea what the
unintended consequences of this change may be.

Here is the diff:

 void
@@ -4863,6 +4868,14 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode,
int *excl)
 		void *m = mmap(NULL, rsize, PROT_READ|PROT_WRITE, MAP_SHARED,
 			env->me_lfd, 0);
 		if (m == MAP_FAILED) goto fail_errno;
+    	
+    	rc = posix_fallocate(env->me_lfd, 0, rsize);
+    	
+    	if (rc) {
+        	munmap(m, rsize);
+        	goto fail;
+    	}
+    	
 		env->me_txns = m;
 #endif
 	}


I'm not sure if this next one is an issue or just incorrect usage on my part. 
So take with a grain of salt.  

After getting an EIO (deliberate out of storage space) from a mdb_txn_commit,
the transaction would be mdb_txn_abort()ed. I then would close then env which
would get a SIGABORT from a double-free on the env_close0 with env->txn0.

The hack I put in there to avoid this was in the mdb_txn_end.  I check if txn ==
env->me_txn0, and if it is, to set env->me_txn0 to NULL.

Here's the diff:

@@ -3244,12 +3244,17 @@ mdb_txn_end(MDB_txn *txn, unsigned mode)
 		}
 		pthread_mutex_unlock(&env->me_rpmutex);
 		tl[0].mid = 0;
-		if (mode & MDB_END_FREE)
+    	if (mode & MDB_END_FREE)
 			free(tl);
 	}
 #endif
-	if (mode & MDB_END_FREE)
-		free(txn);
+    if (mode & MDB_END_FREE) {
+        /* avoid double free on env close */
+        if(txn == env->me_txn0){
+            env->me_txn0 = NULL;
+        }
+        free(txn);
+    }
 }