[nautilus-actions] Only use g_spawn_async_with_pipes when required by execution mode



commit 85930da632d35cdd303e9618a90216000e196158
Author: Pierre Wieser <pwieser trychlos org>
Date:   Fri Mar 11 15:19:13 2011 +0100

    Only use g_spawn_async_with_pipes when required by execution mode
    
    Work-around for #644289.

 ChangeLog            |    7 ++++
 src/core/na-tokens.c |   91 +++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 79 insertions(+), 19 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8caf7a0..3411bb0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-03-11 Pierre Wieser <pwieser trychlos org>
+
+	* src/core/na-tokens.c (execute_action_command):
+	Only use g_spawn_async_with_pipes when required by execution mode
+	(work-around for #644289).
+	Do not close child pid before the end of the child process.
+
 2011-02-26 Pierre Wieser <pwieser trychlos org>
 
 	* configure.ac: Post-release bump version.
diff --git a/src/core/na-tokens.c b/src/core/na-tokens.c
index ac66f9e..bdb7239 100644
--- a/src/core/na-tokens.c
+++ b/src/core/na-tokens.c
@@ -69,6 +69,16 @@ struct _NATokensPrivate {
 	gchar   *scheme;
 };
 
+/*  the structure passed to the callback which waits for the end of the child
+ */
+typedef struct {
+	gchar   *command;
+	gboolean is_output_displayed;
+	gint     child_stdout;
+	gint     child_stderr;
+}
+	ChildStr;
+
 static GObjectClass *st_parent_class = NULL;
 
 static GType     register_type( void );
@@ -77,6 +87,8 @@ static void      instance_init( GTypeInstance *instance, gpointer klass );
 static void      instance_dispose( GObject *object );
 static void      instance_finalize( GObject *object );
 
+static void      child_watch_fn( GPid pid, gint status, ChildStr *child_str );
+static void      display_output( const gchar *command, int fd_stdout, int fd_stderr );
 static gchar    *display_output_get_content( int fd );
 static void      execute_action_command( gchar *command, const NAObjectProfile *profile );
 static gchar    *get_command_execution_display_output( const gchar *command );
@@ -397,6 +409,20 @@ na_tokens_execute_action( const NATokens *tokens, const NAObjectProfile *profile
 }
 
 static void
+child_watch_fn( GPid pid, gint status, ChildStr *child_str )
+{
+	static const gchar *thisfn = "na_tokens_child_watch_fn";
+
+	g_debug( "%s: pid=%u, status=%d", thisfn, ( guint ) pid, status );
+	g_spawn_close_pid( pid );
+	if( child_str->is_output_displayed ){
+		display_output( child_str->command, child_str->child_stdout, child_str->child_stderr );
+	}
+	g_free( child_str->command );
+	g_free( child_str );
+}
+
+static void
 display_output( const gchar *command, int fd_stdout, int fd_stderr )
 {
 	GtkWidget *dialog;
@@ -473,12 +499,14 @@ execute_action_command( gchar *command, const NAObjectProfile *profile )
 	gint argc;
 	gchar *wdir;
 	GPid child_pid;
-	gint child_stdout, child_stderr;
+	ChildStr *child_str;
 
 	g_debug( "%s: profile=%p", thisfn, ( void * ) profile );
 
 	error = NULL;
 	run_command = NULL;
+	child_str = g_new0( ChildStr, 1 );
+	child_pid = ( GPid ) 0;
 	execution_mode = na_object_get_execution_mode( profile );
 
 	if( !strcmp( execution_mode, "Normal" )){
@@ -491,6 +519,7 @@ execute_action_command( gchar *command, const NAObjectProfile *profile )
 		run_command = get_command_execution_embedded( command );
 
 	} else if( !strcmp( execution_mode, "DisplayOutput" )){
+		child_str->is_output_displayed = TRUE;
 		run_command = get_command_execution_display_output( command );
 
 	} else {
@@ -498,6 +527,8 @@ execute_action_command( gchar *command, const NAObjectProfile *profile )
 	}
 
 	if( run_command ){
+		child_str->command = g_strdup( run_command );
+
 		if( !g_shell_parse_argv( run_command, &argc, &argv, &error )){
 			g_warning( "%s: g_shell_parse_argv: %s", thisfn, error->message );
 			g_error_free( error );
@@ -506,27 +537,44 @@ execute_action_command( gchar *command, const NAObjectProfile *profile )
 			wdir = na_object_get_working_dir( profile );
 			g_debug( "%s: run_command=%s, wdir=%s", thisfn, run_command, wdir );
 
-			g_spawn_async_with_pipes( wdir,
-					argv,
-					NULL,
-					G_SPAWN_SEARCH_PATH,
-					NULL,
-					NULL,
-					&child_pid,
-					NULL,
-					&child_stdout,
-					&child_stderr,
-					&error );
+			/* it appears that at least mplayer does not support g_spawn_async_with_pipes
+			 * (at least when notrun in '-quiet' mode) while, e.g., totem and vlc rightly
+			 * support this function
+			 * So only use g_spawn_async_with_pipes when we really need to get back
+			 * the content of output and error streams
+			 * See https://bugzilla.gnome.org/show_bug.cgi?id=644289.
+			 */
+			if( child_str->is_output_displayed ){
+				g_spawn_async_with_pipes( wdir,
+						argv,
+						NULL,
+						G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+						NULL,
+						NULL,
+						&child_pid,
+						NULL,
+						&child_str->child_stdout,
+						&child_str->child_stderr,
+						&error );
+
+			} else {
+				g_spawn_async( wdir,
+						argv,
+						NULL,
+						G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+						NULL,
+						NULL,
+						&child_pid,
+						&error );
+			}
+
 			if( error ){
-				g_warning( "%s: g_spawn_async_with_pipes: %s", thisfn, error->message );
+				g_warning( "%s: g_spawn_async: %s", thisfn, error->message );
 				g_error_free( error );
+				child_pid = ( GPid ) 0;
 
 			} else {
-				g_spawn_close_pid( child_pid );
-
-				if( !strcmp( execution_mode, "DisplayOutput" )){
-					display_output( run_command, child_stdout, child_stderr );
-				}
+				g_child_watch_add( child_pid, ( GChildWatchFunc ) child_watch_fn, child_str );
 			}
 
 			g_free( wdir );
@@ -537,12 +585,17 @@ execute_action_command( gchar *command, const NAObjectProfile *profile )
 	}
 
 	g_free( execution_mode );
+
+	if( child_pid == ( GPid ) 0 ){
+		g_free( child_str->command );
+		g_free( child_str );
+	}
 }
 
 static gchar *
 get_command_execution_display_output( const gchar *command )
 {
-	static const gchar *bin_sh = "/bin/sh -c \"%s\"";
+	static const gchar *bin_sh = "/bin/sh -c COMMAND";
 	return( na_tokens_command_for_terminal( bin_sh, command ));
 }
 



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