aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2010-06-09 08:01:42 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2010-06-09 08:01:42 +0000
commitbb4bce018962c5d7a0bb0776911e516ba78401c2 (patch)
tree298cf55eeb87ed5c63f7a8ba22f62b9c7d4c52cb
parentbf8f09d3ba0cb9722a4aac217b3b2f49fc9b6683 (diff)
action.c: prevent double free when using %f.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2566 ee746299-78ed-0310-b773-934348b2243d
-rw-r--r--ChangeLog5
-rw-r--r--src/action.c29
2 files changed, 28 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 2a10372e..b6dbf1cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2010-06-09
+
+ * src/action.c: prevent double free when using %f.
+ Obtain thread lock in gdk_input_add() callbacks.
+
2010-06-07
* libsylph/prefs_common.[ch]
diff --git a/src/action.c b/src/action.c
index 1fc39335..894945b2 100644
--- a/src/action.c
+++ b/src/action.c
@@ -668,7 +668,7 @@ static gboolean execute_actions(gchar *action, GSList *msg_list,
g_free(user_hidden_str);
if (!children_list) {
- /* If not waiting for children, return */
+ /* If not waiting for children, return */
free_children(children);
} else {
GSList *cur;
@@ -787,9 +787,9 @@ static ChildInfo *fork_child(gchar *cmd, const gchar *msg_str,
close(chld_err[1]);
close(chld_status[0]);
- debug_print("Child: Waiting for grandchild\n");
+ debug_print("Child: Waiting for grandchild (PID: %d)\n", gch_pid);
waitpid(gch_pid, NULL, 0);
- debug_print("Child: grandchild ended\n");
+ debug_print("Child: grandchild ended (PID: %d)\n", gch_pid);
write(chld_status[1], "0\n", 2);
close(chld_status[1]);
}
@@ -838,6 +838,8 @@ static ChildInfo *fork_child(gchar *cmd, const gchar *msg_str,
child_info->tag_err = gdk_input_add(chld_err[0], GDK_INPUT_READ,
catch_output, child_info);
+ debug_print("Monitoring child (PID: %d)\n", pid);
+
if (!(children->action_type &
(ACTION_PIPE_IN | ACTION_PIPE_OUT | ACTION_INSERT)))
return child_info;
@@ -879,6 +881,8 @@ static gint wait_for_children(Children *children)
GSList *cur;
gint nb = children->nb;
+ debug_print("wait_for_children (%p)\n", children);
+
children->nb = 0;
cur = children->list;
@@ -900,7 +904,7 @@ static gint wait_for_children(Children *children)
return FALSE;
if (!children->dialog) {
- free_children(children);
+ /* free_children(children); */
} else if (!children->output) {
gtk_widget_destroy(children->dialog);
}
@@ -983,6 +987,7 @@ static void free_children(Children *children)
child_info = (ChildInfo *)children->list->data;
#ifdef G_OS_UNIX
if (child_info->pid != 0) {
+ debug_print("free_children: waiting PID %d\n", child_info->pid);
if (waitpid(child_info->pid, NULL, 0)
!= child_info->pid) {
perror("waitpid (free_children)");
@@ -1170,10 +1175,12 @@ static void catch_status(gpointer data, gint source, GdkInputCondition cond)
gchar buf;
gint c;
+ gdk_threads_enter();
+
gdk_input_remove(child_info->tag_status);
c = read(source, &buf, 1);
- debug_print("Child returned %c\n", buf);
+ debug_print("Child (PID: %d) returned %c\n", child_info->pid, buf);
#ifdef G_OS_UNIX
waitpid(child_info->pid, NULL, 0);
@@ -1182,6 +1189,8 @@ static void catch_status(gpointer data, gint source, GdkInputCondition cond)
child_info->pid = 0;
wait_for_children(child_info->children);
+
+ gdk_threads_leave();
}
static void catch_input(gpointer data, gint source, GdkInputCondition cond)
@@ -1195,6 +1204,8 @@ static void catch_input(gpointer data, gint source, GdkInputCondition cond)
if (!(cond && GDK_INPUT_WRITE))
return;
+ gdk_threads_enter();
+
gdk_input_remove(child_info->tag_in);
child_info->tag_in = -1;
@@ -1219,6 +1230,8 @@ static void catch_input(gpointer data, gint source, GdkInputCondition cond)
close(child_info->chld_in);
child_info->chld_in = -1;
debug_print("Input to grand child sent.\n");
+
+ gdk_threads_leave();
}
static void catch_output(gpointer data, gint source, GdkInputCondition cond)
@@ -1227,7 +1240,9 @@ static void catch_output(gpointer data, gint source, GdkInputCondition cond)
gint c;
gchar buf[BUFFSIZE];
- debug_print("Catching grand child's output.\n");
+ gdk_threads_enter();
+
+ debug_print("Catching grand child's output (child PID: %d).\n", child_info->pid);
if (child_info->children->action_type &
(ACTION_PIPE_OUT | ACTION_INSERT)
&& source == child_info->chld_out) {
@@ -1302,6 +1317,8 @@ static void catch_output(gpointer data, gint source, GdkInputCondition cond)
}
wait_for_children(child_info->children);
+
+ gdk_threads_leave();
}
static gchar *get_user_string(const gchar *action, ActionType type)