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

Python plugin API locking (patch)



  This patch should protect all plugin API functions with a global
recursive mutex.

  Regards.

-- 
Gustavo J. A. M. Carneiro
<gjc@inescporto.pt> <gustavo@users.sourceforge.net>
diff -rup xchat-2.0.5/src/common/plugin.c xchat-2.0.5-gjc/src/common/plugin.c
--- xchat-2.0.5/src/common/plugin.c	2003-09-21 11:28:08.000000000 +0100
+++ xchat-2.0.5-gjc/src/common/plugin.c	2003-10-03 22:23:08.000000000 +0100
@@ -48,6 +47,12 @@ typedef struct session xchat_context;
 
 #define DEBUG(t) PrintText(0,t)
 
+static GStaticRecMutex xchat_api_lock = G_STATIC_REC_MUTEX_INIT;
+
+#define xchat_plugin_api_lock() g_static_rec_mutex_lock (&xchat_api_lock)
+#define xchat_plugin_api_unlock() g_static_rec_mutex_lock (&xchat_api_lock)
+
+
 /* crafted to be an even 32 bytes */
 struct _xchat_hook
 {
@@ -187,7 +192,9 @@ plugin_list_add (xchat_context *ctx, cha
 	pl->deinit_callback = deinit_func;
 	pl->fake = fake;
 
+	xchat_plugin_api_lock();
 	plugin_list = g_slist_prepend (plugin_list, pl);
+	xchat_plugin_api_unlock();
 
 	return pl;
 }
@@ -673,10 +680,12 @@ plugin_show_help (session *sess, char *c
 void *
 xchat_unhook (xchat_plugin *ph, xchat_hook *hook)
 {
+	xchat_plugin_api_lock();
 	/* perl.c trips this */
-	if (hook->type == HOOK_DELETED || !g_slist_find (hook_list, hook))
+	if (hook->type == HOOK_DELETED || !g_slist_find (hook_list, hook)) {
+		xchat_plugin_api_unlock();
 		return NULL;
-
+	}
 	if (hook->type == HOOK_TIMER && hook->tag != 0)
 		fe_timeout_remove (hook->tag);
 
@@ -690,6 +699,7 @@ xchat_unhook (xchat_plugin *ph, xchat_ho
 	if (hook->help_text)
 		free (hook->help_text);	/* NULL for non-commands */
 
+	xchat_plugin_api_unlock();
 	return hook->userdata;
 }
 
@@ -697,29 +707,49 @@ xchat_hook *
 xchat_hook_command (xchat_plugin *ph, char *name, int pri, xchat_cmd_cb *callb,
 					 	  char *help_text, void *userdata)
 {
-	return plugin_add_hook (ph, HOOK_COMMAND, pri, name, help_text, callb, 0,
+	xchat_hook *retval;
+
+	xchat_plugin_api_lock();
+	retval = plugin_add_hook (ph, HOOK_COMMAND, pri, name, help_text, callb, 0,
 									userdata);
+	xchat_plugin_api_unlock();
+	return retval;
 }
 
 xchat_hook *
 xchat_hook_server (xchat_plugin *ph, char *name, int pri, xchat_serv_cb *callb,
 					 	 void *userdata)
 {
-	return plugin_add_hook (ph, HOOK_SERVER, pri, name, 0, callb, 0, userdata);
+	xchat_hook *retval;
+
+	xchat_plugin_api_lock();
+	retval = plugin_add_hook (ph, HOOK_SERVER, pri, name, 0, callb, 0, userdata);
+	xchat_plugin_api_unlock();
+	return retval;
 }
 
 xchat_hook *
 xchat_hook_print (xchat_plugin *ph, char *name, int pri, xchat_print_cb *callb,
 					   void *userdata)
 {
-	return plugin_add_hook (ph, HOOK_PRINT, pri, name, 0, callb, 0, userdata);
+	xchat_hook *retval;
+
+	xchat_plugin_api_lock();
+	retval = plugin_add_hook (ph, HOOK_PRINT, pri, name, 0, callb, 0, userdata);
+	xchat_plugin_api_unlock();
+	return retval;
 }
 
 xchat_hook *
 xchat_hook_timer (xchat_plugin *ph, int timeout, xchat_timer_cb *callb,
 					   void *userdata)
 {
-	return plugin_add_hook (ph, HOOK_TIMER, 0, 0, 0, callb, timeout, userdata);
+	xchat_hook *retval;
+
+	xchat_plugin_api_lock();
+	retval = plugin_add_hook (ph, HOOK_TIMER, 0, 0, 0, callb, timeout, userdata);
+	xchat_plugin_api_unlock();
+	return retval;
 }
 
 xchat_hook *
@@ -728,10 +758,12 @@ xchat_hook_fd (xchat_plugin *ph, int fd,
 {
 	xchat_hook *hook;
 
+	xchat_plugin_api_lock();
 	hook = plugin_add_hook (ph, HOOK_FD, 0, 0, 0, callb, 0, userdata);
 	hook->pri = fd;
 	/* plugin hook_fd flags correspond exactly to FIA_* flags (fe.h) */
 	hook->tag = fe_input_add (fd, flags, plugin_fd_cb, hook);
+	xchat_plugin_api_unlock();
 
 	return hook;
 }
@@ -739,13 +771,16 @@ xchat_hook_fd (xchat_plugin *ph, int fd,
 void
 xchat_print (xchat_plugin *ph, char *text)
 {
+	xchat_plugin_api_lock();
 	if (!is_session (ph->context))
 	{
 		DEBUG("xchat_print called without a valid context.\n");
+		xchat_plugin_api_unlock();
 		return;
 	}
 
 	PrintText (ph->context, text);
+	xchat_plugin_api_unlock();
 }
 
 void
@@ -765,13 +800,16 @@ xchat_printf (xchat_plugin *ph, char *fo
 void
 xchat_command (xchat_plugin *ph, char *command)
 {
+	xchat_plugin_api_lock();
 	if (!is_session (ph->context))
 	{
 		DEBUG("xchat_command called without a valid context.\n");
+		xchat_plugin_api_unlock();
 		return;
 	}
 
 	handle_command (ph->context, command, FALSE);
+	xchat_plugin_api_unlock();
 }
 
 void
@@ -791,7 +829,11 @@ xchat_commandf (xchat_plugin *ph, char *
 int
 xchat_nickcmp (xchat_plugin *ph, char *s1, char *s2)
 {
-	return ((session *)ph->context)->server->p_cmp (s1, s2);
+	int rv;
+	xchat_plugin_api_lock();
+	rv =  ((session *)ph->context)->server->p_cmp (s1, s2);
+	xchat_plugin_api_unlock();
+	return rv;
 }
 
 xchat_context *
@@ -803,11 +845,14 @@ xchat_get_context (xchat_plugin *ph)
 int
 xchat_set_context (xchat_plugin *ph, xchat_context *context)
 {
+	xchat_plugin_api_lock();
 	if (is_session (context))
 	{
 		ph->context = context;
+		xchat_plugin_api_unlock();
 		return 1;
 	}
+	xchat_plugin_api_unlock();
 	return 0;
 }
 
@@ -817,10 +862,13 @@ xchat_find_context (xchat_plugin *ph, ch
 	GSList *slist, *clist;
 	server *serv;
 	session *sess;
+	xchat_context *retval = NULL;
 
 	if (servname == NULL && channel == NULL)
 		return current_sess;
 
+	xchat_plugin_api_lock();
+
 	slist = serv_list;
 	while (slist)
 	{
@@ -830,8 +878,10 @@ xchat_find_context (xchat_plugin *ph, ch
 			 strcasecmp (servname, serv->hostname) == 0 ||
 			 (serv->networkname && strcasecmp (servname, serv->networkname) == 0))
 		{
-			if (channel == NULL)
-				return serv->front_session;
+			if (channel == NULL) {
+				retval = serv->front_session;
+				goto exit;
+			}
 
 			clist = sess_list;
 			while (clist)
@@ -839,27 +889,33 @@ xchat_find_context (xchat_plugin *ph, ch
 				sess = clist->data;
 				if (sess->server == serv)
 				{
-					if (rfc_casecmp (channel, sess->channel) == 0)
-						return sess;
+					if (rfc_casecmp (channel, sess->channel) == 0) {
+						retval = sess;
+						goto exit;
+					}
 				}
 				clist = clist->next;
 			}
 		}
 		slist = slist->next;
 	}
-
-	return NULL;
+exit:
+	xchat_plugin_api_unlock();
+	return retval;
 }
 
 const char *
 xchat_get_info (xchat_plugin *ph, const char *id)
 {
 	session *sess;
+	const char *retval = NULL;
 
+	xchat_plugin_api_lock();
 	sess = ph->context;
 	if (!is_session (sess))
 	{
 		DEBUG("xchat_get_info called without a valid context.\n");
+		xchat_plugin_api_unlock();
 		return NULL;
 	}
 
@@ -867,43 +923,47 @@ xchat_get_info (xchat_plugin *ph, const 
 	{
 	case 0x2de2ee: /* away */
 		if (sess->server->is_away)
-			return sess->server->last_away_reason;
-		return NULL;
+			retval = sess->server->last_away_reason;
+		break;
 
   	case 0x2c0b7d03: /* channel */
-		return sess->channel;
+		retval = sess->channel; break;
 
 	case 0x30f5a8: /* host */
-		return sess->server->hostname;
+		retval = sess->server->hostname; break;
 
 	case 0x6de15a2e:	/* network */
-		return sess->server->networkname;
+		retval = sess->server->networkname; break;
 
 	case 0x339763: /* nick */
-		return sess->server->nick;
+		retval = sess->server->nick; break;
 
 	case 0xca022f43: /* server */
-		if (!sess->server->connected)
-			return NULL;
-		return sess->server->servername;
+		if (sess->server->connected)
+			retval = sess->server->servername; break;
 
 	case 0x696cd2f: /* topic */
-		return sess->topic;
+		retval = sess->topic; break;
 
 	case 0x14f51cd8: /* version */
-		return VERSION;
+		retval = VERSION; break;
 
 	case 0xdd9b1abd:	/* xchatdir */
-		return get_xdir ();
+		retval = get_xdir (); break;
 	}
 
-	return NULL;
+	xchat_plugin_api_unlock();
+
+	return retval;
 }
 
 int
 xchat_get_prefs (xchat_plugin *ph, const char *name, const char **string, int *integer)
 {
 	int i = 0;
+	int retval = 0;
+
+	xchat_plugin_api_lock();
 
 	do
 	{
@@ -913,11 +973,11 @@ xchat_get_prefs (xchat_plugin *ph, const
 			{
 			case TYPE_STR:
 				*string = ((char *) &prefs + vars[i].offset);
-				return 1;
+				retval = 1; break;
 
 			case TYPE_INT:
 				*integer = *((int *) &prefs + vars[i].offset);
-				return 2;
+				retval = 2; break;
 
 			default:
 			/*case TYPE_BOOL:*/
@@ -925,14 +985,16 @@ xchat_get_prefs (xchat_plugin *ph, const
 					*integer = 1;
 				else
 					*integer = 0;
-				return 3;
+				retval = 3;
 			}
 		}
 		i++;
 	}
 	while (vars[i].name);
 
-	return 0;
+	xchat_plugin_api_unlock();
+
+	return retval;
 }
 
 xchat_list *
@@ -942,6 +1004,7 @@ xchat_list_get (xchat_plugin *ph, const 
 
 	list = malloc (sizeof (xchat_list));
 	list->pos = NULL;
+	xchat_plugin_api_lock();
 
 	switch (str_hash (name))
 	{
@@ -970,9 +1033,10 @@ xchat_list_get (xchat_plugin *ph, const 
 
 	default:
 		free (list);
-		return NULL;
+		list = NULL;
 	}
 
+	xchat_plugin_api_unlock();
 	return list;
 }
 
@@ -1151,9 +1215,11 @@ xchat_plugingui_add (xchat_plugin *ph, c
 							char *version, char *reserved)
 {
 #ifdef USE_PLUGIN
+	xchat_plugin_api_lock();
 	ph = plugin_list_add (NULL, strdup (filename), name, desc, version, NULL,
 								 NULL, TRUE);
 	fe_pluginlist_update ();
+	xchat_plugin_api_unlock();
 #endif
 
 	return ph;
@@ -1163,7 +1229,9 @@ void
 xchat_plugingui_remove (xchat_plugin *ph, void *handle)
 {
 #ifdef USE_PLUGIN
+	xchat_plugin_api_lock();
 	plugin_free (handle, FALSE, FALSE);
+	xchat_plugin_api_unlock();
 #endif
 }
 
@@ -1186,8 +1254,10 @@ xchat_emit_print (xchat_plugin *ph, char
 			break;
 	}
 
+	xchat_plugin_api_lock();
 	i = text_emit_by_name (event_name, ph->context, argv[0], argv[1],
 								  argv[2], argv[3]);
+	xchat_plugin_api_unlock();
 	va_end (args);
 
 	return i;
diff -rup xchat-2.0.5/src/common/xchat.c xchat-2.0.5-gjc/src/common/xchat.c
--- xchat-2.0.5/src/common/xchat.c	2003-09-12 16:15:20.000000000 +0100
+++ xchat-2.0.5-gjc/src/common/xchat.c	2003-10-03 22:25:33.000000000 +0100
@@ -795,6 +795,8 @@ xchat_init (void)
 	char buf[2048];
 	const char *cs = NULL;
 
+	if (!g_thread_supported ()) g_thread_init (NULL);
+
 #ifdef WIN32
 	WSADATA wsadata;