rpms/nspluginwrapper/devel nspluginwrapper-0.9.91.5-restart.patch, NONE, 1.1 nspluginwrapper-0.9.91.5-rpc-error.patch, NONE, 1.1 nspluginwrapper-0.9.91.5-rh.patch, 1.1, 1.2 nspluginwrapper.spec, 1.16, 1.17

Martin Stransky (stransky) fedora-extras-commits at redhat.com
Mon Sep 10 08:44:46 UTC 2007


Author: stransky

Update of /cvs/pkgs/rpms/nspluginwrapper/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv23025

Modified Files:
	nspluginwrapper-0.9.91.5-rh.patch nspluginwrapper.spec 
Added Files:
	nspluginwrapper-0.9.91.5-restart.patch 
	nspluginwrapper-0.9.91.5-rpc-error.patch 
Log Message:
added upstream patches - RPC error handling and plugin restart

nspluginwrapper-0.9.91.5-restart.patch:

--- NEW FILE nspluginwrapper-0.9.91.5-restart.patch ---
Index: src/npw-viewer.c
===================================================================
--- src/npw-viewer.c	(révision 466)
+++ src/npw-viewer.c	(révision 470)
@@ -2268,6 +2268,8 @@
 {
   D(bug("handle_NPP_New\n"));
 
+  rpc_connection_ref(connection);
+
   uint32_t instance_id;
   NPMIMEType plugin_type;
   int32_t mode;
@@ -2344,7 +2346,10 @@
 
   NPSavedData *save_area;
   NPError ret = g_NPP_Destroy(instance, &save_area);
-  return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_NP_SAVED_DATA, save_area, RPC_TYPE_INVALID);
+
+  error = rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_NP_SAVED_DATA, save_area, RPC_TYPE_INVALID);
+  rpc_connection_unref(connection);
+  return error;
 }
 
 // NPP_SetWindow
@@ -2654,13 +2659,13 @@
 g_NPP_WriteReady(NPP instance, NPStream *stream)
 {
   if (instance == NULL)
-	return NPERR_INVALID_INSTANCE_ERROR;
+	return 0;
 
   if (plugin_funcs.writeready == NULL)
-	return NPERR_INVALID_FUNCTABLE_ERROR;
+	return 0;
 
   if (stream == NULL)
-	return NPERR_INVALID_PARAM;
+	return 0;
 
   D(bug("NPP_WriteReady instance=%p, stream=%p\n", instance, stream));
   int32 ret = plugin_funcs.writeready(instance, stream);
@@ -3086,7 +3091,7 @@
   if (g_user_agent)
 	free(g_user_agent);
   if (g_rpc_connection)
-	rpc_exit(g_rpc_connection);
+	rpc_connection_unref(g_rpc_connection);
 
   id_kill();
   return 0;
Index: src/npw-wrapper.c
===================================================================
--- src/npw-wrapper.c	(révision 466)
+++ src/npw-wrapper.c	(révision 470)
@@ -21,6 +21,7 @@
 #define _GNU_SOURCE 1 /* RTLD_DEFAULT */
 #include "sysdeps.h"
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -73,6 +74,9 @@
 // Netscape exported functions
 static NPNetscapeFuncs mozilla_funcs;
 
+// NPAPI version nspluginwrapper supports
+static int npapi_version = 0;
+
 // Wrapper plugin data
 typedef struct {
   int initialized;
@@ -89,6 +93,7 @@
 typedef struct _PluginInstance {
   NPP instance;
   uint32_t instance_id;
+  rpc_connection_t *connection;
 } PluginInstance;
 
 // Plugin side data for an NPStream instance
@@ -101,7 +106,38 @@
 // Prototypes
 static void plugin_init(int is_NP_Initialize);
 static void plugin_exit(void);
+static NPError plugin_restart_if_needed(void);
 
+/*
+ *  Notes concerning NSPluginWrapper recovery model.
+ *
+ *  NSPluginWrapper will restart the Viewer if it detected to be
+ *  dead. It will not attempt to "replay" the plugin. This means that
+ *  if a plugin crashed, its window will remain grayed: only new
+ *  instances will start a new viewer.
+ *
+ *  Each PlugInstance holds a reference to the RPC connection it was
+ *  created with. g_rpc_connection can be seen as the "master"
+ *  connection (used to initialize and shutdown things). The RPC
+ *  connections are reference counted so that when the master
+ *  connection is set to a new one, previous connections are still
+ *  live. That way, old NPP instances are not passed down with the new
+ *  connection and thus can fail early/gracefully in subsequent calls
+ *  to NPP_*() functions.
+ *
+ *  TODO: make NPRuntime aware of per-plugin connections? This
+ *  shouldn't matter from the Wrapper side because npruntime requests
+ *  come from the Viewer side (see NPN_*() handlers). XXX: even with a
+ *  running script (NPClass handlers)?
+ */
+
+// Minimal time between two plugin restarts in sec
+#define MIN_RESTART_INTERVAL 1
+
+// Consume as many bytes as possible when we are not NPP_WriteReady()
+// XXX: move to a common place to Wrapper and Viewer
+#define NPERR_STREAM_BUFSIZ 65536
+
 // Helpers
 #ifndef min
 #define min(x, y) ((x) < (y) ? (x) : (y))
@@ -110,7 +146,16 @@
 #define max(x, y) ((x) > (y) ? (x) : (y))
 #endif
 
+#define PLUGIN_INSTANCE(INSTANCE) plugin_instance(INSTANCE)
 
+static inline PluginInstance *plugin_instance(NPP instance)
+{
+  PluginInstance *plugin = (PluginInstance *)instance->pdata;
+  assert(plugin->instance == instance);
+  return plugin;
+}
+
+
 /* ====================================================================== */
 /* === RPC communication                                              === */
 /* ====================================================================== */
@@ -1177,13 +1222,13 @@
 
 // Creates a new instance of a plug-in
 static NPError
-invoke_NPP_New(NPMIMEType mime_type, NPP instance,
+invoke_NPP_New(PluginInstance *plugin, NPMIMEType mime_type,
 			   uint16_t mode, int16_t argc, char *argn[], char *argv[],
 			   NPSavedData *saved)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_NEW,
-								RPC_TYPE_UINT32, ((PluginInstance *)instance->pdata)->instance_id,
+								RPC_TYPE_UINT32, plugin->instance_id,
 								RPC_TYPE_STRING, mime_type,
 								RPC_TYPE_INT32, (int32_t)mode,
 								RPC_TYPE_ARRAY, RPC_TYPE_STRING, (uint32_t)argc, argn,
@@ -1197,7 +1242,7 @@
   }
 
   int32_t ret;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_INVALID);
 
@@ -1216,17 +1261,25 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
-
+	
+  // Check if we need to restart the plug-in
+  NPError ret = plugin_restart_if_needed();
+  if (ret != NPERR_NO_ERROR)
+  	return ret;
+		
   PluginInstance *plugin = malloc(sizeof(*plugin));
   if (plugin == NULL)
 	return NPERR_OUT_OF_MEMORY_ERROR;
   memset(plugin, 0, sizeof(*plugin));
   plugin->instance = instance;
   plugin->instance_id = id_create(plugin);
+  plugin->connection = g_rpc_connection;
   instance->pdata = plugin;
 
+  rpc_connection_ref(plugin->connection);
+
   D(bug("NPP_New instance=%p\n", instance));
-  NPError ret = invoke_NPP_New(mime_type, instance, mode, argc, argn, argv, saved);
+  ret = invoke_NPP_New(plugin, mime_type, mode, argc, argn, argv, saved);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
 
   if (saved) {
@@ -1240,11 +1293,11 @@
 
 // Deletes a specific instance of a plug-in
 static NPError
-invoke_NPP_Destroy(NPP instance, NPSavedData **save)
+invoke_NPP_Destroy(PluginInstance *plugin, NPSavedData **save)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_DESTROY,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_INVALID);
 
   if (error != RPC_ERROR_NO_ERROR) {
@@ -1254,7 +1307,7 @@
 
   int32_t ret;
   NPSavedData *save_area = NULL;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_NP_SAVED_DATA, &save_area,
 									RPC_TYPE_INVALID);
@@ -1280,28 +1333,29 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   D(bug("NPP_Destroy instance=%p\n", instance));
-  NPError ret = invoke_NPP_Destroy(instance, save);
+  NPError ret = invoke_NPP_Destroy(plugin, save);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
 
-  PluginInstance *plugin = instance->pdata;
-  if (plugin) {
-	id_remove(plugin->instance_id);
-	free(plugin);
-	instance->pdata = NULL;
-  }
+  rpc_connection_unref(plugin->connection);
 
+  id_remove(plugin->instance_id);
+  free(plugin);
+  instance->pdata = NULL;
   return ret;
 }
 
 // Tells the plug-in when a window is created, moved, sized, or destroyed
 static NPError
-invoke_NPP_SetWindow(NPP instance, NPWindow *window)
+invoke_NPP_SetWindow(PluginInstance *plugin, NPWindow *window)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_SET_WINDOW,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_NP_WINDOW, window,
 								RPC_TYPE_INVALID);
 
@@ -1311,7 +1365,7 @@
   }
 
   int32_t ret;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_INVALID);
 
@@ -1328,20 +1382,23 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   D(bug("NPP_SetWindow instance=%p\n", instance));
-  NPError ret = invoke_NPP_SetWindow(instance, window);
+  NPError ret = invoke_NPP_SetWindow(plugin, window);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
   return ret;
 }
 
 // Allows the browser to query the plug-in for information
 static NPError
-invoke_NPP_GetValue(NPP instance, NPPVariable variable, void *value)
+invoke_NPP_GetValue(PluginInstance *plugin, NPPVariable variable, void *value)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_GET_VALUE,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_INT32, variable,
 								RPC_TYPE_INVALID);
 
@@ -1355,7 +1412,7 @@
   case RPC_TYPE_STRING:
 	{
 	  char *str = NULL;
-	  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID);
+	  error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID);
 	  if (error != RPC_ERROR_NO_ERROR) {
 		npw_perror("NPP_GetValue() wait for reply", error);
 		ret = NPERR_GENERIC_ERROR;
@@ -1384,7 +1441,7 @@
   case RPC_TYPE_INT32:
 	{
 	  int32_t n = 0;
-	  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INT32, &n, RPC_TYPE_INVALID);
+	  error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INT32, &n, RPC_TYPE_INVALID);
 	  if (error != RPC_ERROR_NO_ERROR) {
 		npw_perror("NPP_GetValue() wait for reply", error);
 		ret = NPERR_GENERIC_ERROR;
@@ -1396,7 +1453,7 @@
   case RPC_TYPE_BOOLEAN:
 	{
 	  uint32_t b = 0;
-	  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_BOOLEAN, &b, RPC_TYPE_INVALID);
+	  error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_BOOLEAN, &b, RPC_TYPE_INVALID);
 	  if (error != RPC_ERROR_NO_ERROR) {
 		npw_perror("NPP_GetValue() wait for reply", error);
 		ret = NPERR_GENERIC_ERROR;
@@ -1408,7 +1465,7 @@
   case RPC_TYPE_NP_OBJECT:
 	{
 	  NPObject *npobj = NULL;
-	  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_NP_OBJECT, &npobj, RPC_TYPE_INVALID);
+	  error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_NP_OBJECT, &npobj, RPC_TYPE_INVALID);
 	  if (error != RPC_ERROR_NO_ERROR) {
 		npw_perror("NPP_GetValue() wait for reply", error);
 		ret = NPERR_GENERIC_ERROR;
@@ -1427,6 +1484,9 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   switch (rpc_type_of_NPPVariable(variable)) {
   case RPC_TYPE_STRING:
@@ -1440,14 +1500,14 @@
   }
 
   D(bug("NPP_GetValue instance=%p, variable=%d\n", instance, variable));
-  NPError ret = invoke_NPP_GetValue(instance, variable, value);
+  NPError ret = invoke_NPP_GetValue(plugin, variable, value);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
   return ret;
 }
 
 // Sets information about the plug-in
 static NPError
-invoke_NPP_SetValue(NPP instance, NPPVariable variable, void *value)
+invoke_NPP_SetValue(PluginInstance *plugin, NPPVariable variable, void *value)
 {
   UNIMPLEMENTED();
 
@@ -1459,20 +1519,23 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   D(bug("NPP_SetValue instance=%p, variable=%d\n", instance, variable));
-  NPError ret = invoke_NPP_SetValue(instance, variable, value);
+  NPError ret = invoke_NPP_SetValue(plugin, variable, value);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
   return NPERR_GENERIC_ERROR;
 }
 
 // Notifies the instance of the completion of a URL request
 static void
-invoke_NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
+invoke_NPP_URLNotify(PluginInstance *plugin, const char *url, NPReason reason, void *notifyData)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_URL_NOTIFY,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_STRING, url,
 								RPC_TYPE_INT32, reason,
 								RPC_TYPE_NP_NOTIFY_DATA, notifyData,
@@ -1483,7 +1546,7 @@
 	return;
   }
 
-  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INVALID);
+  error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INVALID);
   
   if (error != RPC_ERROR_NO_ERROR)
 	npw_perror("NPP_URLNotify() wait for reply", error);
@@ -1494,19 +1557,22 @@
 {
   if (instance == NULL)
 	return;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return;
 
   D(bug("NPP_URLNotify instance=%p, url='%s', reason=%d, notifyData=%p\n", instance, url, reason, notifyData));
-  invoke_NPP_URLNotify(instance, url, reason, notifyData);
+  invoke_NPP_URLNotify(plugin, url, reason, notifyData);
   D(bug(" done\n"));
 }
 
 // Notifies a plug-in instance of a new data stream
 static NPError
-invoke_NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
+invoke_NPP_NewStream(PluginInstance *plugin, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_NEW_STREAM,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_STRING, type,
 								RPC_TYPE_UINT32, ((StreamInstance *)stream->pdata)->stream_id,
 								RPC_TYPE_STRING, stream->url,
@@ -1524,7 +1590,7 @@
 
   int32_t ret;
   uint32_t r_stype;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_UINT32, &r_stype,
 									RPC_TYPE_NP_NOTIFY_DATA, &stream->notifyData,
@@ -1544,6 +1610,9 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   StreamInstance *stream_pdata = malloc(sizeof(*stream_pdata));
   if (stream_pdata == NULL)
@@ -1555,18 +1624,18 @@
   stream->pdata = stream_pdata;
 
   D(bug("NPP_NewStream instance=%p\n", instance));
-  NPError ret = invoke_NPP_NewStream(instance, type, stream, seekable, stype);
+  NPError ret = invoke_NPP_NewStream(plugin, type, stream, seekable, stype);
   D(bug(" return: %d [%s], stype=%s\n", ret, string_of_NPError(ret), string_of_NPStreamType(*stype)));
   return ret;
 }
 
 // Tells the plug-in that a stream is about to be closed or destroyed
 static NPError
-invoke_NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
+invoke_NPP_DestroyStream(PluginInstance *plugin, NPStream *stream, NPReason reason)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_DESTROY_STREAM,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_NP_STREAM, stream,
 								RPC_TYPE_INT32, reason,
 								RPC_TYPE_INVALID);
@@ -1577,7 +1646,7 @@
   }
 
   int32_t ret;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_INVALID);
 
@@ -1594,9 +1663,12 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   D(bug("NPP_DestroyStream instance=%p\n", instance));
-  NPError ret = invoke_NPP_DestroyStream(instance, stream, reason);
+  NPError ret = invoke_NPP_DestroyStream(plugin, stream, reason);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
 
   StreamInstance *stream_pdata = stream->pdata;
@@ -1611,11 +1683,11 @@
 
 // Provides a local file name for the data from a stream
 static void
-invoke_NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
+invoke_NPP_StreamAsFile(PluginInstance *plugin, NPStream *stream, const char *fname)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_STREAM_AS_FILE,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_NP_STREAM, stream,
 								RPC_TYPE_STRING, fname,
 								RPC_TYPE_INVALID);
@@ -1625,7 +1697,7 @@
 	return;
   }
 
-  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INVALID);
+  error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INVALID);
 
   if (error != RPC_ERROR_NO_ERROR)
 	npw_perror("NPP_StreamAsFile() wait for reply", error);
@@ -1636,35 +1708,38 @@
 {
   if (instance == NULL)
 	return;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return;
 
   D(bug("NPP_StreamAsFile instance=%p\n", instance));
-  invoke_NPP_StreamAsFile(instance, stream, fname);
+  invoke_NPP_StreamAsFile(plugin, stream, fname);
   D(bug(" done\n"));
 }
 
 // Determines maximum number of bytes that the plug-in can consume
 static int32
-invoke_NPP_WriteReady(NPP instance, NPStream *stream)
+invoke_NPP_WriteReady(PluginInstance *plugin, NPStream *stream)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_WRITE_READY,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_NP_STREAM, stream,
 								RPC_TYPE_INVALID);
 
   if (error != RPC_ERROR_NO_ERROR) {
 	npw_perror("NPP_WriteReady() invoke", error);
-	return 0;
+	return NPERR_STREAM_BUFSIZ;
   }
 
   int32_t ret;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_INVALID);
 
   if (error != RPC_ERROR_NO_ERROR) {
 	npw_perror("NPP_WriteReady() wait for reply", error);
-	return 0;
+	return NPERR_STREAM_BUFSIZ;
   }
 
   return ret;
@@ -1674,10 +1749,13 @@
 g_NPP_WriteReady(NPP instance, NPStream *stream)
 {
   if (instance == NULL)
-	return -1;
+	return 0;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return 0;
 
   D(bug("NPP_WriteReady instance=%p\n", instance));
-  int32 ret = invoke_NPP_WriteReady(instance, stream);
+  int32 ret = invoke_NPP_WriteReady(plugin, stream);
   D(bug(" return: %d\n", ret));
   return ret;
 }
@@ -1685,11 +1763,11 @@
 
 // Delivers data to a plug-in instance
 static int32
-invoke_NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buf)
+invoke_NPP_Write(PluginInstance *plugin, NPStream *stream, int32 offset, int32 len, void *buf)
 {
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_WRITE,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_NP_STREAM, stream,
 								RPC_TYPE_INT32, offset,
 								RPC_TYPE_ARRAY, RPC_TYPE_CHAR, len, buf,
@@ -1701,7 +1779,7 @@
   }
 
   int32_t ret;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_INT32, &ret,
 									RPC_TYPE_INVALID);
 
@@ -1718,16 +1796,19 @@
 {
   if (instance == NULL)
 	return -1;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return -1;
 
   D(bug("NPP_Write instance=%p\n", instance));
-  int32 ret = invoke_NPP_Write(instance, stream, offset, len, buf);
+  int32 ret = invoke_NPP_Write(plugin, stream, offset, len, buf);
   D(bug(" return: %d\n", ret));
   return ret;
 }
 
 
 // Requests a platform-specific print operation for an embedded or full-screen plug-in
-static void invoke_NPP_Print(NPP instance, NPPrint *PrintInfo)
+static void invoke_NPP_Print(PluginInstance *plugin, NPPrint *PrintInfo)
 {
   NPPrintCallbackStruct *platformPrint;
   switch (PrintInfo->mode) {
@@ -1746,9 +1827,9 @@
 	platform_print_id = id_create(platformPrint);
   D(bug(" platformPrint=%p\n", platformPrint));
 
-  int error = rpc_method_invoke(g_rpc_connection,
+  int error = rpc_method_invoke(plugin->connection,
 								RPC_METHOD_NPP_PRINT,
-								RPC_TYPE_NPP, instance,
+								RPC_TYPE_NPP, plugin->instance,
 								RPC_TYPE_UINT32, platform_print_id,
 								RPC_TYPE_NP_PRINT, PrintInfo,
 								RPC_TYPE_INVALID);
@@ -1759,7 +1840,7 @@
   }
 
   uint32_t pluginPrinted;
-  error = rpc_method_wait_for_reply(g_rpc_connection,
+  error = rpc_method_wait_for_reply(plugin->connection,
 									RPC_TYPE_BOOLEAN, &pluginPrinted,
 									RPC_TYPE_INVALID);
 
@@ -1780,17 +1861,20 @@
 {
   if (instance == NULL)
 	return;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return;
 
   if (PrintInfo == NULL)
 	return;
 
   D(bug("NPP_Print instance=%p\n", instance));
-  invoke_NPP_Print(instance, PrintInfo);
+  invoke_NPP_Print(plugin, PrintInfo);
   D(bug(" done\n"));
 }
 
 // Delivers a platform-specific window event to the instance
-static int16 invoke_NPP_HandleEvent(NPP instance, void *event)
+static int16 invoke_NPP_HandleEvent(PluginInstance *plugin, void *event)
 {
   UNIMPLEMENTED();
 
@@ -1801,9 +1885,12 @@
 {
   if (instance == NULL)
 	return NPERR_INVALID_INSTANCE_ERROR;
+  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
+  if (plugin == NULL)
+	return NPERR_INVALID_INSTANCE_ERROR;
 
   D(bug("NPP_HandleEvent instance=%p\n", instance));
-  int16 ret = invoke_NPP_HandleEvent(instance, event);
+  int16 ret = invoke_NPP_HandleEvent(plugin, event);
   D(bug(" return: ret\n", ret));
   return ret;
 }
@@ -2206,10 +2293,10 @@
 g_LONG64_NPP_WriteReady(NPP instance, void *stream)
 {
   if (instance == NULL)
-	return -1L;
+	return 0;
 
   if (stream == NULL)
-	return -1L;
+	return 0;
 
   return (int64)(int32)g_NPP_WriteReady(instance, NP_STREAM32(stream));
 }
@@ -2310,6 +2397,30 @@
 }
 
 // Provides global initialization for a plug-in
+static NPError
+invoke_NP_Initialize(uint32_t npapi_version)
+{
+  int error = rpc_method_invoke(g_rpc_connection,
+								RPC_METHOD_NP_INITIALIZE,
+								RPC_TYPE_UINT32, npapi_version,
+								RPC_TYPE_INVALID);
+
+  if (error != RPC_ERROR_NO_ERROR) {
+	npw_perror("NP_Initialize() invoke", error);
+	return NPERR_MODULE_LOAD_FAILED_ERROR;
+  }
+
+  int32_t ret;
+  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
+
+  if (error != RPC_ERROR_NO_ERROR) {
+	npw_perror("NP_Initialize() wait for reply", error);
+	return NPERR_MODULE_LOAD_FAILED_ERROR;
+  }
+
+  return ret;
+}
+
 NPError
 NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
 {
@@ -2374,26 +2485,9 @@
 
   // pass down common NPAPI version supported by both the underlying
   // browser and the thunking capabilities of nspluginwrapper
-  uint32_t version = min(moz_funcs->version, plugin_funcs->version);
+  npapi_version = min(moz_funcs->version, plugin_funcs->version);
 
-  int error = rpc_method_invoke(g_rpc_connection,
-								RPC_METHOD_NP_INITIALIZE,
-								RPC_TYPE_UINT32, (uint32_t)version,
-								RPC_TYPE_INVALID);
-
-  if (error != RPC_ERROR_NO_ERROR) {
-	npw_perror("NP_Initialize() invoke", error);
-	return NPERR_MODULE_LOAD_FAILED_ERROR;
-  }
-
-  int32_t ret;
-  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
-
-  if (error != RPC_ERROR_NO_ERROR) {
-	npw_perror("NP_Initialize() wait for reply", error);
-	return NPERR_MODULE_LOAD_FAILED_ERROR;
-  }
-
+  NPError ret = invoke_NP_Initialize(npapi_version);
   D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
   return ret;
 }
@@ -2657,7 +2751,7 @@
   }
 
   if (g_rpc_connection) {
-	rpc_exit(g_rpc_connection);
+	rpc_connection_unref(g_rpc_connection);
 	g_rpc_connection = NULL;
   }
 
@@ -2708,3 +2802,40 @@
 	g_plugin.description = NULL;
   }
 }
+
+static NPError plugin_restart(void)
+{
+  if (g_plugin.is_wrapper)
+	return NPERR_NO_ERROR;
+
+  // Shut it down    
+  plugin_exit();
+  g_plugin.initialized = 0;
+  g_plugin.viewer_pid = -1;
+  g_plugin.is_wrapper = 0;
+
+  // And start it again
+  plugin_init(1);
+  if (g_plugin.initialized <= 0)
+	return NPERR_MODULE_LOAD_FAILED_ERROR;
+
+  return invoke_NP_Initialize(npapi_version);
+}
+
+static NPError plugin_restart_if_needed(void)
+{
+  if (rpc_status(g_rpc_connection) != RPC_STATUS_ACTIVE) {
+	static time_t last_restart = 0;
+	time_t now = time(NULL);
+	if (now - last_restart < MIN_RESTART_INTERVAL)
+	  return NPERR_GENERIC_ERROR;
+	last_restart = now;
+
+	D(bug("Restart plugins viewer\n"));
+	NPError ret = plugin_restart();
+	D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
+	return ret;
+  }
+
+  return NPERR_NO_ERROR;
+}
Index: src/rpc.c
===================================================================
--- src/rpc.c	(révision 466)
+++ src/rpc.c	(révision 470)
@@ -289,6 +289,7 @@
 // Client / Server connection
 struct rpc_connection_t {
   int type;
+  int refcnt;
   int status;
   int socket;
   char *socket_path;
@@ -301,6 +302,22 @@
   char send_buffer[BUFSIZ];
 };
 
+// Increment connection reference count
+void rpc_connection_ref(rpc_connection_t *connection)
+{
+  if (connection)
+	++connection->refcnt;
+}
+
+// Decrement connection reference count and destroy it if it reaches zero
+void rpc_connection_unref(rpc_connection_t *connection)
+{
+  if (connection && --connection->refcnt == 0) {
+	D(bug("Close unused connection\n"));
+	rpc_exit(connection);
+  }
+}
+
 // Returns connection status
 static inline int _rpc_status(rpc_connection_t *connection)
 {
@@ -417,6 +434,7 @@
   if (connection == NULL)
 	return NULL;
   connection->type = RPC_CONNECTION_SERVER;
+  connection->refcnt = 1;
   connection->status = RPC_STATUS_CLOSED;
   connection->socket = -1;
   connection->server_thread_active = 0;
@@ -468,6 +486,7 @@
   if (connection == NULL)
 	return NULL;
   connection->type = RPC_CONNECTION_CLIENT;
+  connection->refcnt = 1;
   connection->status = RPC_STATUS_CLOSED;
   connection->server_socket = -1;
   connection->callbacks = NULL;
Index: src/rpc.h
===================================================================
--- src/rpc.h	(révision 466)
+++ src/rpc.h	(révision 470)
@@ -42,6 +42,9 @@
 
 // Connection Handling
 typedef struct rpc_connection_t rpc_connection_t;
+extern void rpc_connection_ref(rpc_connection_t *connection) attribute_hidden;
+extern void rpc_connection_unref(rpc_connection_t *connection) attribute_hidden;
+
 extern rpc_connection_t *rpc_init_server(const char *ident) attribute_hidden;
 extern rpc_connection_t *rpc_init_client(const char *ident) attribute_hidden;
 extern int rpc_exit(rpc_connection_t *connection) attribute_hidden;
Index: NEWS
===================================================================
--- NEWS	(révision 466)
+++ NEWS	(révision 470)
@@ -1,6 +1,9 @@
-nspluginwrapper NEWS -- history of user-visible changes.  2007-08-26
+nspluginwrapper NEWS -- history of user-visible changes.  2007-MM-DD
 Copyright (C) 2005-2007 Gwenole Beauchesne
 
+Version 0.9.92 (BETA) - DD.MMM.2007
+* Restart plugins viewer on error (Martin Stransky)
+
 Version 0.9.91.5 (BETA) - 26.Aug.2007
 * Fix a memory leak in NPP_Destroy()
 * Fix DiamondX XEmbed example plugin

nspluginwrapper-0.9.91.5-rpc-error.patch:

--- NEW FILE nspluginwrapper-0.9.91.5-rpc-error.patch ---
Index: src/rpc.c
===================================================================
--- src/rpc.c	(révision 460)
+++ src/rpc.c	(révision 466)
@@ -29,6 +29,7 @@
 
 #include "sysdeps.h"
 
+#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
@@ -288,6 +289,7 @@
 // Client / Server connection
 struct rpc_connection_t {
   int type;
+  int status;
   int socket;
   char *socket_path;
   int server_socket;
@@ -299,6 +301,47 @@
   char send_buffer[BUFSIZ];
 };
 
+// Returns connection status
+static inline int _rpc_status(rpc_connection_t *connection)
+{
+  return connection->status;
+}
+
+int rpc_status(rpc_connection_t *connection)
+{
+  if (connection == NULL)
+	return RPC_STATUS_BROKEN;
+  return _rpc_status(connection);
+}
+
+// Set connection status
+static void _rpc_set_status(rpc_connection_t *connection, int error)
+{
+  if (connection->status == RPC_STATUS_ACTIVE) {
+	switch (error) {
+	case RPC_ERROR_NO_ERROR:
+	  connection->status = RPC_STATUS_ACTIVE;
+	  break;
+	case RPC_ERROR_CONNECTION_CLOSED:
+	  connection->status = RPC_STATUS_CLOSED;
+	  break;
+	default:
+	  connection->status = RPC_STATUS_BROKEN;
+	  break;
+	}
+  }
+}
+
+static inline int rpc_error(rpc_connection_t *connection, int error)
+{
+  // XXX: this function must be called only in case of error
+  // (otherwise, it's an internal error)
+  assert(error < 0);
+  assert(connection != NULL);
+  _rpc_set_status(connection, error);
+  return error;
+}
+
 // Returns socket fd or -1 if invalid connection
 int rpc_socket(rpc_connection_t *connection)
 {
@@ -374,6 +417,7 @@
   if (connection == NULL)
 	return NULL;
   connection->type = RPC_CONNECTION_SERVER;
+  connection->status = RPC_STATUS_CLOSED;
   connection->socket = -1;
   connection->server_thread_active = 0;
   connection->callbacks = NULL;
@@ -404,6 +448,7 @@
 	return NULL;
   }
 
+  connection->status = RPC_STATUS_ACTIVE;
   return connection;
 }
 
@@ -423,6 +468,7 @@
   if (connection == NULL)
 	return NULL;
   connection->type = RPC_CONNECTION_CLIENT;
+  connection->status = RPC_STATUS_CLOSED;
   connection->server_socket = -1;
   connection->callbacks = NULL;
   connection->n_callbacks = 0;
@@ -467,6 +513,7 @@
 	return NULL;
   }
 
+  connection->status = RPC_STATUS_ACTIVE;
   return connection;
 }
 
@@ -1334,11 +1381,14 @@
   int32_t msg_tag;
   int error = rpc_message_recv_int32(&message, &msg_tag);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   if (msg_tag != RPC_MESSAGE_START)
-	return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 
-  return _rpc_dispatch(connection, &message);
+  int method = _rpc_dispatch(connection, &message);
+  if (method < 0)
+	return rpc_error(connection, method);
+  return method;
 }
 
 
@@ -1443,6 +1493,8 @@
 
   if (connection == NULL)
 	return RPC_ERROR_CONNECTION_NULL;
+  if (_rpc_status(connection) == RPC_STATUS_CLOSED)
+	return RPC_ERROR_CONNECTION_CLOSED;
 
   rpc_message_t message;
   rpc_message_init(&message, connection);
@@ -1459,24 +1511,24 @@
   // send: <invoke> = MESSAGE_START <method-id> MESSAGE_END
   int error = rpc_message_send_int32(&message, RPC_MESSAGE_START);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   error = rpc_message_send_int32(&message, method);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   error = rpc_message_send_int32(&message, RPC_MESSAGE_END);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   error = rpc_message_flush(&message);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
 
   // wait: MESSAGE_ACK
   int32_t msg_tag;
   error = rpc_message_recv_int32(&message, &msg_tag);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   if (msg_tag != RPC_MESSAGE_ACK)
-	return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 
   // send optional arguments
   va_list args;
@@ -1490,19 +1542,19 @@
 	error = rpc_message_send_args(&message, args);
 	va_end(args);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 	error = rpc_message_flush(&message);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 
 	// wait: MESSAGE_ACK
 	error = rpc_message_recv_int32(&message, &msg_tag);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 	if (msg_tag != RPC_MESSAGE_ACK)
-	  return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
   }
-  
+
   return RPC_ERROR_NO_ERROR;
 }
 
@@ -1513,6 +1565,8 @@
 
   if (connection == NULL)
 	return RPC_ERROR_CONNECTION_NULL;
+  if (_rpc_status(connection) == RPC_STATUS_CLOSED)
+	return RPC_ERROR_CONNECTION_CLOSED;
 
   rpc_message_t message;
   rpc_message_init(&message, connection);
@@ -1523,15 +1577,15 @@
   int error = rpc_message_recv_args(&message, args);
   va_end(args);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
 
   // send: MESSAGE_ACK
   error = rpc_message_send_int32(&message, RPC_MESSAGE_ACK);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   error = rpc_message_flush(&message);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
 
   return RPC_ERROR_NO_ERROR;
 }
@@ -1547,6 +1601,8 @@
 
   if (connection == NULL)
 	return RPC_ERROR_CONNECTION_NULL;
+  if (_rpc_status(connection) == RPC_STATUS_CLOSED)
+	return RPC_ERROR_CONNECTION_CLOSED;
 
   rpc_message_init(&message, connection);
   va_start(args, connection);
@@ -1559,11 +1615,11 @@
   while (!done) {
 	error = rpc_message_recv_int32(&message, &msg_tag);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 	switch (msg_tag) {
 	case RPC_MESSAGE_START:
 	  if ((error = _rpc_dispatch(connection, &message)) < 0)
-		return error;
+		return rpc_error(connection, error);
 	  break;
 	case RPC_MESSAGE_REPLY:
 	case RPC_MESSAGE_ACK:
@@ -1575,11 +1631,12 @@
 		int32_t error_code;
 		error = rpc_message_recv_int32(&message, &error_code);
 		if (error != RPC_ERROR_NO_ERROR)
-		  return error;
-		return error_code;
+		  return rpc_error(connection, error);
+		// return other-side error code
+		return rpc_error(connection, error_code);
 	  }
 	default:
-	  return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 	}
   }
 
@@ -1587,35 +1644,35 @@
 
 	// wait: <reply>
 	if (msg_tag != RPC_MESSAGE_REPLY)
-	  return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 	va_start(args, connection);
 	error = rpc_message_recv_args(&message, args);
 	va_end(args);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 	error = rpc_message_recv_int32(&message, &msg_tag);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 	if (msg_tag != RPC_MESSAGE_END)
-	  return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	  return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 
 	// send: MESSAGE_ACK
 	error = rpc_message_send_int32(&message, RPC_MESSAGE_ACK);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 	error = rpc_message_flush(&message);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
 
 	// wait: MESSAGE_ACK (prepare for final ACK)
 	error = rpc_message_recv_int32(&message, &msg_tag);
 	if (error != RPC_ERROR_NO_ERROR)
-	  return error;
+	  return rpc_error(connection, error);
   }
 
   // wait: MESSAGE_ACK
   if (msg_tag != RPC_MESSAGE_ACK)
-	return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
   
   return RPC_ERROR_NO_ERROR;
 }
@@ -1626,7 +1683,9 @@
   D(bug("rpc_method_send_reply\n"));
 
   if (connection == NULL)
-	return RPC_ERROR_GENERIC;
+	return RPC_ERROR_CONNECTION_NULL;
+  if (_rpc_status(connection) == RPC_STATUS_CLOSED)
+	return RPC_ERROR_CONNECTION_CLOSED;
 
   rpc_message_t message;
   rpc_message_init(&message, connection);
@@ -1634,27 +1693,27 @@
   // send: <reply> = MESSAGE_REPLY [ <method-args> ] MESSAGE_END
   int error = rpc_message_send_int32(&message, RPC_MESSAGE_REPLY);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   va_list args;
   va_start(args, connection);
   error = rpc_message_send_args(&message, args);
   va_end(args);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   error = rpc_message_send_int32(&message, RPC_MESSAGE_END);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   error = rpc_message_flush(&message);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
 
   // wait: MESSAGE_ACK
   int32_t msg_tag;
   error = rpc_message_recv_int32(&message, &msg_tag);
   if (error != RPC_ERROR_NO_ERROR)
-	return error;
+	return rpc_error(connection, error);
   if (msg_tag != RPC_MESSAGE_ACK)
-	return RPC_ERROR_MESSAGE_TYPE_INVALID;
+	return rpc_error(connection, RPC_ERROR_MESSAGE_TYPE_INVALID);
 
   return RPC_ERROR_NO_ERROR;
 }
Index: src/rpc.h
===================================================================
--- src/rpc.h	(révision 460)
+++ src/rpc.h	(révision 466)
@@ -51,6 +51,13 @@
 extern int rpc_wait_dispatch(rpc_connection_t *connection, int timeout) attribute_hidden;
 extern int rpc_socket(rpc_connection_t *connection) attribute_hidden;
 
+enum {
+  RPC_STATUS_BROKEN						= -1,
+  RPC_STATUS_CLOSED						= 0,
+  RPC_STATUS_ACTIVE						= 1,
+};
+extern int rpc_status(rpc_connection_t *connection) attribute_hidden;
+
 // Message Passing
 enum {
   RPC_TYPE_INVALID						=  0,

nspluginwrapper-0.9.91.5-rh.patch:

Index: nspluginwrapper-0.9.91.5-rh.patch
===================================================================
RCS file: /cvs/pkgs/rpms/nspluginwrapper/devel/nspluginwrapper-0.9.91.5-rh.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- nspluginwrapper-0.9.91.5-rh.patch	28 Aug 2007 11:12:58 -0000	1.1
+++ nspluginwrapper-0.9.91.5-rh.patch	10 Sep 2007 08:44:43 -0000	1.2
@@ -643,28 +643,6 @@
  #include "utils.h"
  
  #define XP_UNIX 1
-@@ -85,6 +86,8 @@ typedef struct {
- 
- static Plugin g_plugin = { 0, -1, 0, NULL, NULL, NULL };
- 
-+static uint32_t version = 0;
-+
- // Instance state information about the plugin
- typedef struct _PluginInstance {
-   NPP instance;
-@@ -101,6 +104,12 @@ typedef struct _StreamInstance {
- // Prototypes
- static void plugin_init(int is_NP_Initialize);
- static void plugin_exit(void);
-+static NPError plugin_restart(void);
-+static NPError check_restart(void);
-+static time_t  last_restart = 0; 
-+
-+// Minimal time between two plugin restarts in sec
-+#define RESTART_INTERVAL      1
- 
- // Helpers
- #ifndef min
 @@ -211,7 +220,7 @@ g_NPN_GetValue(NPP instance, NPNVariable
    if (mozilla_funcs.getvalue == NULL)
  	return NPERR_INVALID_FUNCTABLE_ERROR;
@@ -682,20 +660,6 @@
    abort();
  }
  
-@@ -1216,7 +1226,12 @@ g_NPP_New(NPMIMEType mime_type, NPP inst
- {
-   if (instance == NULL)
- 	return NPERR_INVALID_INSTANCE_ERROR;
--
-+	
-+  // Check if we need to restart the plug-in
-+  NPError rt = check_restart();
-+  if(rt != NPERR_NO_ERROR)
-+  	return(rt);
-+		
-   PluginInstance *plugin = malloc(sizeof(*plugin));
-   if (plugin == NULL)
- 	return NPERR_OUT_OF_MEMORY_ERROR;
 @@ -1485,8 +1500,9 @@ invoke_NPP_URLNotify(NPP instance, const
  
    error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INVALID);
@@ -707,15 +671,6 @@
  }
  
  static void
-@@ -2374,7 +2390,7 @@ NP_Initialize(NPNetscapeFuncs *moz_funcs
- 
-   // pass down common NPAPI version supported by both the underlying
-   // browser and the thunking capabilities of nspluginwrapper
--  uint32_t version = min(moz_funcs->version, plugin_funcs->version);
-+  version = min(moz_funcs->version, plugin_funcs->version);
- 
-   int error = rpc_method_invoke(g_rpc_connection,
- 								RPC_METHOD_NP_INITIALIZE,
 @@ -2467,9 +2483,9 @@ static void plugin_init(int is_NP_Initia
    static int init_count = 0;
    ++init_count;
@@ -728,71 +683,6 @@
  
    // Cache MIME info and plugin name/description
    if (g_plugin.name == NULL && g_plugin.description == NULL && g_plugin.formats == NULL) {
-@@ -2708,3 +2724,64 @@ static void __attribute__((destructor)) 
- 	g_plugin.description = NULL;
-   }
- }
-+
-+static NPError plugin_restart(void)
-+{
-+  if(!g_plugin.is_wrapper) {
-+	D(bug("plugin restart\n"));
-+
-+	// Shut it down    
-+	plugin_exit();
-+
-+	g_plugin.initialized = 0;
-+	g_plugin.viewer_pid = -1;
-+	g_plugin.is_wrapper = 0;
-+
-+	// And start it again
-+	plugin_init(1);
-+	if (g_plugin.initialized <= 0)
-+		return NPERR_MODULE_LOAD_FAILED_ERROR;
-+		
-+	int error = rpc_method_invoke(g_rpc_connection,
-+				RPC_METHOD_NP_INITIALIZE,
-+				RPC_TYPE_UINT32, (uint32_t)version,
-+				RPC_TYPE_INVALID);
-+	
-+	if (error != RPC_ERROR_NO_ERROR) {
-+		npw_perror("NP_Initialize() invoke", error);
-+		return NPERR_MODULE_LOAD_FAILED_ERROR;
-+	}
-+	
-+	int32_t ret;
-+	error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
-+	
-+	if (error != RPC_ERROR_NO_ERROR) {
-+		npw_perror("NP_Initialize() wait for reply", error);
-+		return NPERR_MODULE_LOAD_FAILED_ERROR;
-+	}
-+	
-+	D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
-+	return ret;
-+  }
-+  return NPERR_NO_ERROR;
-+}
-+
-+static NPError check_restart(void)
-+{
-+	if(rpc_status_get(g_rpc_connection)) {
-+
-+		time_t atime = time(NULL);
-+		if(atime - last_restart < RESTART_INTERVAL)
-+			return(NPERR_GENERIC_ERROR);
-+		last_restart = atime;
-+
-+		D(bug("Plugin restart\n"));
-+		int ret = plugin_restart();
-+		if(ret == NPERR_NO_ERROR) {			
-+			rpc_error_clear(g_rpc_connection);
-+		}		
-+		D(bug("check_restart return %d [%s]\n", ret, string_of_NPError(ret)));
-+		return(ret);
-+	}	
-+	return(NPERR_NO_ERROR);
-+}
 --- /dev/null	2007-08-28 09:06:54.719628589 +0200
 +++ nspluginwrapper-0.9.91.5/src/npw-dir.c	2007-08-28 11:10:19.000000000 +0200
 @@ -0,0 +1,97 @@
@@ -1405,326 +1295,3 @@
    }
  
    return 0;
---- nspluginwrapper-0.9.91.5/src/rpc.h.rh	2007-03-04 16:01:22.000000000 +0100
-+++ nspluginwrapper-0.9.91.5/src/rpc.h	2007-08-28 11:10:19.000000000 +0200
-@@ -103,4 +103,11 @@ extern int rpc_method_wait_for_reply(rpc
- extern int rpc_method_get_args(rpc_connection_t *connection, ...) attribute_hidden;
- extern int rpc_method_send_reply(rpc_connection_t *connection, ...) attribute_hidden;
- 
-+// Error handling
-+void rpc_error_check(rpc_connection_t *connection, int err_code);
-+int  rpc_error_get(rpc_connection_t *connection);
-+void rpc_error_set(rpc_connection_t *connection);
-+void rpc_error_clear(rpc_connection_t *connection);
-+int  rpc_status_get(rpc_connection_t *connection);
-+
- #endif /* RPC_H */
---- nspluginwrapper-0.9.91.5/src/rpc.c.rh	2007-04-02 22:03:07.000000000 +0200
-+++ nspluginwrapper-0.9.91.5/src/rpc.c	2007-08-28 11:10:19.000000000 +0200
-@@ -232,6 +232,7 @@ const char *rpc_strerror(int error)
-   return str;
- }
- 
-+
- // Set non blocking I/O on the specified socket
- static int rpc_set_non_blocking_io(int socket)
- {
-@@ -293,12 +294,41 @@ struct rpc_connection_t {
-   int server_socket;
-   int server_thread_active;
-   pthread_t server_thread;
-+  int last_error;
-   rpc_method_descriptor_t *callbacks;
-   int n_callbacks;
-   int send_offset;
-   char send_buffer[BUFSIZ];
- };
- 
-+#define ERROR_RPC(error)  ((error) > -1100 && (error) <= -1000)
-+
-+void rpc_error_check(rpc_connection_t *connection, int err_code)
-+{
-+  if(ERROR_RPC(err_code))
-+	connection->last_error = err_code;
-+}
-+
-+int  rpc_error_get(rpc_connection_t *connection)
-+{	
-+  return(connection->last_error);
-+}
-+
-+void rpc_error_set(rpc_connection_t *connection)
-+{	
-+  connection->last_error = RPC_ERROR_GENERIC;
-+}
-+
-+void rpc_error_clear(rpc_connection_t *connection)
-+{
-+  connection->last_error = 0;
-+}
-+
-+int  rpc_status_get(rpc_connection_t *connection)
-+{	
-+  return(ERROR_RPC(connection->last_error));
-+}
-+
- // Returns socket fd or -1 if invalid connection
- int rpc_socket(rpc_connection_t *connection)
- {
-@@ -378,6 +408,7 @@ rpc_connection_t *rpc_init_server(const 
-   connection->server_thread_active = 0;
-   connection->callbacks = NULL;
-   connection->n_callbacks = 0;
-+	connection->last_error = 0;
- 
-   if ((connection->server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- 	perror("server socket");
-@@ -426,6 +457,7 @@ rpc_connection_t *rpc_init_client(const 
-   connection->server_socket = -1;
-   connection->callbacks = NULL;
-   connection->n_callbacks = 0;
-+	connection->last_error = 0;
- 
-   if ((connection->socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- 	perror("client socket");
-@@ -1441,8 +1473,9 @@ int rpc_method_invoke(rpc_connection_t *
- {
-   D(bug("rpc_method_invoke method=%d\n", method));
- 
--  if (connection == NULL)
-+  if (connection == NULL) {
- 	return RPC_ERROR_CONNECTION_NULL;
-+  }
- 
-   rpc_message_t message;
-   rpc_message_init(&message, connection);
-@@ -1452,29 +1485,41 @@ int rpc_method_invoke(rpc_connection_t *
- 	int ret = _rpc_wait_dispatch(connection, 0);
- 	if (ret == 0)
- 	  break;
--	if (ret < 0 || (ret = rpc_dispatch(connection)) < 0)
-+	if (ret < 0 || (ret = rpc_dispatch(connection)) < 0) {
-+          rpc_error_check(connection,ret);
- 	  return ret;
-+  	}
-   }
- 
-   // send: <invoke> = MESSAGE_START <method-id> MESSAGE_END
-   int error = rpc_message_send_int32(&message, RPC_MESSAGE_START);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
-   error = rpc_message_send_int32(&message, method);
--  if (error != RPC_ERROR_NO_ERROR)
--	return error;
-+  if (error != RPC_ERROR_NO_ERROR) {
-+        rpc_error_check(connection,error);
-+        return error;
-+  }
-   error = rpc_message_send_int32(&message, RPC_MESSAGE_END);
--  if (error != RPC_ERROR_NO_ERROR)
--	return error;
-+  if (error != RPC_ERROR_NO_ERROR) {
-+        rpc_error_check(connection,error);
-+        return error;
-+  }
-   error = rpc_message_flush(&message);
--  if (error != RPC_ERROR_NO_ERROR)
--	return error;
-+  if (error != RPC_ERROR_NO_ERROR) {
-+        rpc_error_check(connection,error);
-+        return error;
-+  }
- 
-   // wait: MESSAGE_ACK
-   int32_t msg_tag;
-   error = rpc_message_recv_int32(&message, &msg_tag);
--  if (error != RPC_ERROR_NO_ERROR)
--	return error;
-+  if (error != RPC_ERROR_NO_ERROR) {
-+        rpc_error_check(connection,error);
-+        return error;
-+  }
-   if (msg_tag != RPC_MESSAGE_ACK)
- 	return RPC_ERROR_MESSAGE_TYPE_INVALID;
- 
-@@ -1489,16 +1534,22 @@ int rpc_method_invoke(rpc_connection_t *
- 	va_start(args, method);
- 	error = rpc_message_send_args(&message, args);
- 	va_end(args);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+        }
- 	error = rpc_message_flush(&message);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 
- 	// wait: MESSAGE_ACK
- 	error = rpc_message_recv_int32(&message, &msg_tag);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 	if (msg_tag != RPC_MESSAGE_ACK)
- 	  return RPC_ERROR_MESSAGE_TYPE_INVALID;
-   }
-@@ -1522,16 +1573,22 @@ int rpc_method_get_args(rpc_connection_t
-   va_start(args, connection);
-   int error = rpc_message_recv_args(&message, args);
-   va_end(args);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
- 
-   // send: MESSAGE_ACK
-   error = rpc_message_send_int32(&message, RPC_MESSAGE_ACK);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
-   error = rpc_message_flush(&message);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
- 
-   return RPC_ERROR_NO_ERROR;
- }
-@@ -1545,8 +1602,9 @@ int rpc_method_wait_for_reply(rpc_connec
-   va_list args;
-   rpc_message_t message;
- 
--  if (connection == NULL)
-+  if (connection == NULL) {
- 	return RPC_ERROR_CONNECTION_NULL;
-+  }
- 
-   rpc_message_init(&message, connection);
-   va_start(args, connection);
-@@ -1558,12 +1616,16 @@ int rpc_method_wait_for_reply(rpc_connec
-   bool done = false;
-   while (!done) {
- 	error = rpc_message_recv_int32(&message, &msg_tag);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 	switch (msg_tag) {
- 	case RPC_MESSAGE_START:
--	  if ((error = _rpc_dispatch(connection, &message)) < 0)
-+	  if ((error = _rpc_dispatch(connection, &message)) < 0) {
-+		rpc_error_check(connection,error);
- 		return error;
-+	  }
- 	  break;
- 	case RPC_MESSAGE_REPLY:
- 	case RPC_MESSAGE_ACK:
-@@ -1574,8 +1636,10 @@ int rpc_method_wait_for_reply(rpc_connec
- 		// wait: <error-code>
- 		int32_t error_code;
- 		error = rpc_message_recv_int32(&message, &error_code);
--		if (error != RPC_ERROR_NO_ERROR)
-+		if (error != RPC_ERROR_NO_ERROR) {
-+		  rpc_error_check(connection,error);
- 		  return error;
-+		}
- 		return error_code;
- 	  }
- 	default:
-@@ -1591,26 +1655,36 @@ int rpc_method_wait_for_reply(rpc_connec
- 	va_start(args, connection);
- 	error = rpc_message_recv_args(&message, args);
- 	va_end(args);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 	error = rpc_message_recv_int32(&message, &msg_tag);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 	if (msg_tag != RPC_MESSAGE_END)
- 	  return RPC_ERROR_MESSAGE_TYPE_INVALID;
- 
- 	// send: MESSAGE_ACK
- 	error = rpc_message_send_int32(&message, RPC_MESSAGE_ACK);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 	error = rpc_message_flush(&message);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
- 
- 	// wait: MESSAGE_ACK (prepare for final ACK)
- 	error = rpc_message_recv_int32(&message, &msg_tag);
--	if (error != RPC_ERROR_NO_ERROR)
-+	if (error != RPC_ERROR_NO_ERROR) {
-+	  rpc_error_check(connection,error);
- 	  return error;
-+	}
-   }
- 
-   // wait: MESSAGE_ACK
-@@ -1633,26 +1707,36 @@ int rpc_method_send_reply(rpc_connection
- 
-   // send: <reply> = MESSAGE_REPLY [ <method-args> ] MESSAGE_END
-   int error = rpc_message_send_int32(&message, RPC_MESSAGE_REPLY);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
-   va_list args;
-   va_start(args, connection);
-   error = rpc_message_send_args(&message, args);
-   va_end(args);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
-   error = rpc_message_send_int32(&message, RPC_MESSAGE_END);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
-   error = rpc_message_flush(&message);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
- 
-   // wait: MESSAGE_ACK
-   int32_t msg_tag;
-   error = rpc_message_recv_int32(&message, &msg_tag);
--  if (error != RPC_ERROR_NO_ERROR)
-+  if (error != RPC_ERROR_NO_ERROR) {
-+	rpc_error_check(connection,error);
- 	return error;
-+  }
-   if (msg_tag != RPC_MESSAGE_ACK)
- 	return RPC_ERROR_MESSAGE_TYPE_INVALID;
- 


Index: nspluginwrapper.spec
===================================================================
RCS file: /cvs/pkgs/rpms/nspluginwrapper/devel/nspluginwrapper.spec,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- nspluginwrapper.spec	28 Aug 2007 11:12:58 -0000	1.16
+++ nspluginwrapper.spec	10 Sep 2007 08:44:43 -0000	1.17
@@ -70,13 +70,15 @@
 Summary:	A compatibility layer for Netscape 4 plugins
 Name:		nspluginwrapper
 Version:	0.9.91.5
-Release:	1%{?dist}
+Release:	2%{?dist}
 Source0:	%{name}-%{version}%{?svndate:-%{svndate}}.tar.bz2
 Source1:        %{plugin_config_name}.tar.gz 
 Source2:        plugin-config.sh.in
 Source3:        %{name}.sh.in
-Patch0:		nspluginwrapper-0.9.91.5-rh.patch
-Patch1:		nspluginwrapper-0.9.91.4-config.patch
+Patch0:		nspluginwrapper-0.9.91.5-rpc-error.patch
+Patch1:		nspluginwrapper-0.9.91.5-restart.patch
+Patch2:		nspluginwrapper-0.9.91.5-rh.patch
+Patch3:		nspluginwrapper-0.9.91.4-config.patch
 License:	GPL
 Group:		Networking/WWW
 Url:		http://gwenole.beauchesne.info/projects/nspluginwrapper/
@@ -104,8 +106,10 @@
 
 %prep
 %setup  -q -a 1
-%patch0 -p1 -b .rh
-%patch1 -p1 -b .cnf
+%patch0 -p0
+%patch1 -p0
+%patch2 -p1 -b .rh
+%patch3 -p1 -b .cnf
 
 # remove old/incompatibile stuff
 rm -rf npapi
@@ -221,6 +225,9 @@
 %{_sysconfdir}/sysconfig/%{name}
 
 %changelog
+* Mon Sep 10 2007 Martin Stransky <stransky at redhat.com> 0.9.91.5-2
+- added upstream patches - RPC error handling and plugin restart
+
 * Mon Aug 27 2007 Martin Stransky <stransky at redhat.com> 0.9.91.5-1
 - update to the latest upstream
 




More information about the fedora-extras-commits mailing list