commit: r271 - in trunk: daemon libspread

[email protected]
Newsgroups gmane.network.spread.cvs
Message-ID <[email protected]>
Author: jonathan
Date: 2005-08-25 08:41:05 -0400 (Thu, 25 Aug 2005)
New Revision: 271

Modified:
   trunk/daemon/Changelog
   trunk/daemon/mutex.h
   trunk/libspread/sp.c
Log:
Add pthread_atfork handlers to make the spread library safe for threaded
forking programs. The mutex.h header now supports a Mutex_atfork() function
that calls pthread_atfork for pthread based threading systems and does
nothing for Windows. 

Before a fork, the Struct Mutex is acquired and it is released after the
fork in the parent. The child unlocks all mutexes after fork. 
The rule that only one process can actively USE a spread connection
at once is still there. So only the parent or child should make SP_recv
or SP_multicast calls on the connection, not both.


Modified: trunk/daemon/Changelog
===================================================================
--- trunk/daemon/Changelog	2005-08-25 12:35:49 UTC (rev 270)
+++ trunk/daemon/Changelog	2005-08-25 12:41:05 UTC (rev 271)
@@ -1,3 +1,12 @@
+Wed Aug 17 10:00:15 2005  Jonathan Stanton  <[email protected]>
+
+	* sp.c (sp_atfork_child,sp_atfork_parent,sp_initialize_locks): 
+	Add pthread_atfork handlers to 
+	reset mutexes when a client process is forked. They
+	also cause the Struct_mutex to be held over the fork. This 
+	currently only handles pthread based threading and not
+	Windows based threading. 
+
 Mon Aug  8 00:11:24 2005  Jonathan Stanton  <[email protected]>
 
 	* sp.c (SP_kill): Make SP_kill() a public function so apps

Modified: trunk/daemon/mutex.h
===================================================================
--- trunk/daemon/mutex.h	2005-08-25 12:35:49 UTC (rev 270)
+++ trunk/daemon/mutex.h	2005-08-25 12:41:05 UTC (rev 271)
@@ -49,6 +49,8 @@
 
 #define Mutex_trylock( mutex )	 Trylock_firsttime; Trylock_firsttime = 1
 
+#define Mutex_atfork( prepare, parent, child )
+
 #else	/* _REENTRANT */
 
 #ifndef ARCH_PC_WIN95
@@ -63,6 +65,8 @@
 #define Mutex_unlock( mutex )	pthread_mutex_unlock( mutex )
 #define Mutex_trylock( mutex )	pthread_mutex_trylock( mutex )
 
+#define Mutex_atfork( prepare, parent, child )  pthread_atfork( prepare, parent, child )
+
 #else	/* ARCH_PC_WIN95 */
 
 	/* ### Static init is implemented with a problem which cannot be solved */
@@ -79,6 +83,9 @@
 static	int 	Trylock_firsttime = 0;
 #define Mutex_trylock( mutex )	Trylock_firsttime; Trylock_firsttime = 1
 
+/* Not needed? for Windows */
+#define Mutex_atfork( prepare, parent, child )
+
 #endif /* ARCH_PC_WIN95 */
 
 

Modified: trunk/libspread/sp.c
===================================================================
--- trunk/libspread/sp.c	2005-08-25 12:35:49 UTC (rev 270)
+++ trunk/libspread/sp.c	2005-08-25 12:41:05 UTC (rev 271)
@@ -149,6 +149,51 @@
         /* didn't find the method in the list */
         return(0);
 }
+
+/* Lock and threading related functions */
+
+/* reset all mutexes in child process.
+ * This is strictly speaking, unsafe, because a parent thread may have 
+ * a Mutex lock on the mailbox becaue it is reading from the socket
+ * and once the locks in the child are reset, the child process could 
+ * also attempt a read -- resulting in garbage in both processe.
+ * However -- We document and require that spread mailboxes cannot be
+ * read from different processes at the same time, so the application
+ * is responsible for not using them this way. This restriction is true 
+ * even without the mutex reset because the pthread mutexes' are not 
+ * enforced accross processes, but only within the threads of one process.
+ *
+ * What can be done is spread connections can be passed by fork from
+ * a parent process to a child and only used in one of the processes. 
+ * that will now work correctly, even if a parent is also multithreaded.
+ */
+/* We take the Struct_mutex in prepare to prevent inconsistent state 
+ * in Session[] structs in child
+ */
+static  void    sp_atfork_prepare(void)
+{
+
+        Mutex_lock( &Struct_mutex );
+}
+/* parent unlocks Struct_mutex when fork is complete */
+static  void    sp_atfork_parent(void)
+{
+        Mutex_unlock( &Struct_mutex );
+}
+/* Child unlocks Struct_mutex, and also unlocks all Mbox_mutexes so
+ * it can acces all of the connections.
+ */
+static  void    sp_atfork_child(void)
+{
+        int i;
+        Mutex_unlock( &Struct_mutex );
+        for( i=0; i < MAX_MUTEX; i++ )
+        {
+            Mutex_unlock( &Mbox_mutex[i][0] );
+            Mutex_unlock( &Mbox_mutex[i][1] );
+        }
+
+}
 static  void    sp_initialize_locks(void)
 {
         int ret, i;
@@ -167,6 +212,8 @@
 			Mutex_init( &Mbox_mutex[i][0] );
 			Mutex_init( &Mbox_mutex[i][1] );
 		}
+
+                Mutex_atfork( sp_atfork_prepare, sp_atfork_parent, sp_atfork_child );
 #ifdef ARCH_PC_WIN95
 
 		ret = WSAStartup( MAKEWORD(2,0), &WSAData );
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.