diff options
Diffstat (limited to 'security/nss/lib/softoken/keydb.c')
-rw-r--r-- | security/nss/lib/softoken/keydb.c | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 64ae1db76..877ead2b5 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -830,23 +830,25 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, NSSLOWKEYDBHandle *handle, NSSLOWKEYDBNameFunc namecb, void *cbarg) { SECStatus rv = SECFailure; + int status = RDB_FAIL; char *updname = NULL; DB *updatedb = NULL; PRBool updated = PR_FALSE; int ret; if (appName) { - handle->db = rdbopen( appName, prefix, "key", NO_CREATE); + handle->db = rdbopen( appName, prefix, "key", NO_CREATE, &status); } else { handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 ); } /* if create fails then we lose */ if ( handle->db == NULL ) { - return SECFailure; + return (status == RDB_RETRY) ? SECWouldBlock: SECFailure; } rv = db_BeginTransaction(handle->db); if (rv != SECSuccess) { + db_InitComplete(handle->db); return rv; } @@ -855,6 +857,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, if (nsslowkey_version(handle->db) == NSSLOWKEY_DB_FILE_VERSION) { /* someone else has already updated the database for us */ db_FinishTransaction(handle->db, PR_FALSE); + db_InitComplete(handle->db); return SECSuccess; } @@ -872,6 +875,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, db_Copy(handle->db, updatedb); (updatedb->close)(updatedb); db_FinishTransaction(handle->db,PR_FALSE); + db_InitComplete(handle->db); return SECSuccess; } } @@ -924,9 +928,34 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, loser: db_FinishTransaction(handle->db, rv != SECSuccess); + db_InitComplete(handle->db); return rv; } + +static DB * +openOldDB(const char *appName, const char *prefix, const char *dbname, + PRBool openflags, int *version) { + DB *db = NULL; + + if (appName) { + db = rdbopen( appName, prefix, "key", openflags, NULL); + } else { + db = dbopen( dbname, openflags, 0600, DB_HASH, 0 ); + } + + /* check for correct version number */ + if (db != NULL) { + *version = nsslowkey_version(db); + if (*version != NSSLOWKEY_DB_FILE_VERSION ) { + /* bogus version number record, reset the database */ + (* db->close)( db ); + db = NULL; + } + } + return db; +} + NSSLOWKEYDBHandle * nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, NSSLOWKEYDBNameFunc namecb, void *cbarg) @@ -953,25 +982,14 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, handle->dbname = (appName == NULL) ? PORT_Strdup(dbname) : (prefix ? PORT_Strdup(prefix) : NULL); handle->readOnly = readOnly; - - if (appName) { - handle->db = rdbopen( appName, prefix, "key", openflags); - } else { - handle->db = dbopen( dbname, openflags, 0600, DB_HASH, 0 ); - } - /* check for correct version number */ - if (handle->db != NULL) { - handle->version = nsslowkey_version(handle->db); - if (handle->version == 255) { - goto loser; - } - if (handle->version != NSSLOWKEY_DB_FILE_VERSION ) { - /* bogus version number record, reset the database */ - (* handle->db->close)( handle->db ); - handle->db = NULL; - } + + handle->db = openOldDB(appName, prefix, dbname, openflags, + &handle->version); + if (handle->version == 255) { + goto loser; } + /* if first open fails, try to create a new DB */ if ( handle->db == NULL ) { @@ -980,7 +998,16 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, } rv = openNewDB(appName, prefix, dbname, handle, namecb, cbarg); - if (rv != SECSuccess) { + /* two processes started to initialize the database at the same time. + * The multiprocess code blocked the second one, then had it retry to + * see if it can just open the database normally */ + if (rv == SECWouldBlock) { + handle->db = openOldDB(appName,prefix,dbname, + openflags, &handle->version); + if (handle->db == NULL) { + goto loser; + } + } else if (rv != SECSuccess) { goto loser; } @@ -2453,7 +2480,8 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) (* handle->db->close)(handle->db); if (handle->appname) { - handle->db=rdbopen(handle->appname, handle->dbname, "key", NO_CREATE); + handle->db= + rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL); } else { handle->db = dbopen( handle->dbname, NO_CREATE, 0600, DB_HASH, 0 ); } |