[evolution-data-server] Fix for the NSS_Shutdown crash



commit 898b5e05f95bf7703a55aee9ea2e5f87119ed53e
Author: Sergio Villar Senín <svillar igalia com>
Date:   Tue Apr 28 18:29:02 2009 +0200

    Fix for the NSS_Shutdown crash
---
 camel/ChangeLog |    9 +++++++++
 camel/camel.c   |   44 ++++++++++++++++++++++++++++++++++++--------
 2 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/camel/ChangeLog b/camel/ChangeLog
index 3535bfa..fcc2e5c 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,12 @@
+2009-05-07  Sergio Villar Senin  <svillar igalia com>
+
+	** Fix for bug #580620
+
+	* camel.c (camel_init, camel_shutdown): protect calls to NSS_Init
+	and NSS_Shutdown to avoid simultaneous calls from multiple
+	threads. Do not unconditionally cleanup NSS if it was externally
+	initialized.
+
 2009-05-06  Jeff Cai <jeff cai sun com>
 
 	** Fix for bug #581420
diff --git a/camel/camel.c b/camel/camel.c
index d19ffcc..be1855b 100644
--- a/camel/camel.c
+++ b/camel/camel.c
@@ -44,6 +44,18 @@
 #include "camel-provider.h"
 #include "camel-private.h"
 
+#ifdef HAVE_NSS
+/* To protect NSS initialization and shutdown. This prevents
+   concurrent calls to shutdown() and init() by different threads */
+PRLock *nss_initlock = NULL;
+
+/* Whether or not Camel has initialized the NSS library. We cannot
+   unconditionally call NSS_Shutdown() if NSS was initialized by other
+   library before. This boolean ensures that we only perform a cleanup
+   if and only if Camel is the one that previously initialized NSS */
+volatile gboolean nss_initialized = FALSE;
+#endif
+
 static int initialised = FALSE;
 
 int camel_application_is_exiting = FALSE;
@@ -70,7 +82,11 @@ camel_init (const char *configdir, gboolean nss_init)
 		char *nss_configdir;
 		PRUint16 indx;
 
-		PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10);
+		if (nss_initlock == NULL) {
+			PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10);
+			nss_initlock = PR_NewLock();
+		}
+		PR_Lock (nss_initlock);
 		
 #ifndef G_OS_WIN32
 		nss_configdir = g_strdup (configdir);
@@ -78,16 +94,25 @@ camel_init (const char *configdir, gboolean nss_init)
 		nss_configdir = g_win32_locale_filename_from_utf8 (configdir);
 #endif
 
-		if (NSS_InitReadWrite (nss_configdir) == SECFailure) {
-			/* fall back on using volatile dbs? */
-			if (NSS_NoDB_Init (nss_configdir) == SECFailure) {
-				g_free (nss_configdir);
-				g_warning ("Failed to initialize NSS");
-				return -1;
+		if (!NSS_IsInitialized()) {
+			nss_initialized = 1;
+
+			if (NSS_InitReadWrite (nss_configdir) == SECFailure) {
+				/* fall back on using volatile dbs? */
+				if (NSS_NoDB_Init (nss_configdir) == SECFailure) {
+					g_free (nss_configdir);
+					g_warning ("Failed to initialize NSS");
+					nss_initialized = 0;
+					PR_Unlock(nss_initlock);
+					return -1;
+				}
 			}
 		}
 
 		NSS_SetDomesticPolicy ();
+
+		PR_Unlock(nss_initlock);
+
 		/* we must enable all ciphersuites */
 		for (indx = 0; indx < SSL_NumImplementedCiphers; indx++) {
 			if (!SSL_IS_SSL2_CIPHER(SSL_ImplementedCiphers[indx]))
@@ -138,7 +163,10 @@ camel_shutdown (void)
 	/* These next calls must come last. */
 
 #if defined (HAVE_NSS)
-	NSS_Shutdown ();
+	PR_Lock(nss_initlock);
+	if (nss_initialized)
+		NSS_Shutdown ();
+	PR_Unlock(nss_initlock);
 #endif /* HAVE_NSS */
 
 	initialised = FALSE;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]