From: <ik...@us...> - 2008-03-31 01:53:14
|
Revision: 1363 http://cutter.svn.sourceforge.net/cutter/?rev=1363&view=rev Author: ikezoe Date: 2008-03-30 18:53:11 -0700 (Sun, 30 Mar 2008) Log Message: ----------- * cutter/cut-proccess.[c|h]: Added. Modified Paths: -------------- trunk/ChangeLog trunk/cutter/Makefile.am trunk/cutter/cut-test-context.c Added Paths: ----------- trunk/cutter/cut-proccess.c trunk/cutter/cut-proccess.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2008-03-31 01:04:27 UTC (rev 1362) +++ trunk/ChangeLog 2008-03-31 01:53:11 UTC (rev 1363) @@ -2,6 +2,7 @@ * cutter/cut-public.h, cutter/cut-experimental.h: Define APIs to obtain messages from forked proccess. + * cutter/cut-proccess.[c|h]: Added. 2008-03-28 Kouhei Sutou <ko...@co...> Modified: trunk/cutter/Makefile.am =================================================================== --- trunk/cutter/Makefile.am 2008-03-31 01:04:27 UTC (rev 1362) +++ trunk/cutter/Makefile.am 2008-03-31 01:53:11 UTC (rev 1363) @@ -41,6 +41,7 @@ cut-ui-factory-builder.h \ cut-module-factory.h \ cut-report.h \ + cut-proccess.h \ cut-verbose-level.h noinst_headers = \ @@ -115,6 +116,7 @@ cut-ui-factory-builder.c \ cut-module-factory.c \ cut-report.c \ + cut-proccess.c \ cut-utils.c \ cut-value-equal.c Added: trunk/cutter/cut-proccess.c =================================================================== --- trunk/cutter/cut-proccess.c (rev 0) +++ trunk/cutter/cut-proccess.c 2008-03-31 01:53:11 UTC (rev 1363) @@ -0,0 +1,260 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2007 Kouhei Sutou <ko...@co...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <errno.h> +#include <glib.h> +#include <glib/gstdio.h> +#include <gmodule.h> + +#include "cut-proccess.h" +#include "cut-experimental.h" + +#define CUT_PROCCESS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CUT_TYPE_PROCCESS, CutProccessPrivate)) + +typedef struct _CutProccessPrivate CutProccessPrivate; +struct _CutProccessPrivate +{ + pid_t pid; + GString *stdout_string; + GString *stderr_string; +}; + +enum +{ + STDOUT, + STDERR, + CUTTER_PIPE +}; + +G_DEFINE_TYPE (CutProccess, cut_proccess, G_TYPE_OBJECT) + +static void dispose (GObject *object); + +static void +cut_proccess_class_init (CutProccessClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = dispose; + + g_type_class_add_private(gobject_class, sizeof(CutProccessPrivate)); +} + +static int +sane_dup2 (int fd1, int fd2) +{ + int ret; + do + ret = dup2(fd1, fd2); + while (ret < 0 && errno == EINTR); + return ret; +} + +static GString * +get_string (CutProccess *proccess, int type) +{ + CutProccessPrivate *priv = CUT_PROCCESS_GET_PRIVATE(proccess); + GString *string; + + switch (type) { + case STDOUT: + string = priv->stdout_string; + break; + case STDERR: + string = priv->stderr_string; + break; + default: /* Unknown type */ + string = NULL; + } + + return string; +} + +static gboolean +read_from_pipe (CutProccess *proccess, int pipe, int type) +{ + gchar buf[4096]; + ssize_t len; + + len = read(pipe, buf, sizeof(buf)); + if (len > 0) { + GString *string; + string = get_string(proccess, type); + g_string_append_len(string, buf, len); + return TRUE; + } + return FALSE; +} + +static pid_t +prepare_pipes (CutProccess *proccess) +{ + CutProccessPrivate *priv = CUT_PROCCESS_GET_PRIVATE(proccess); + pid_t pid; + int stdout_pipe[2] = { -1, -1 }; + int stderr_pipe[2] = { -1, -1 }; + int stdtst_pipe[2] = { -1, -1 }; + + priv->pid = 0; + + if (pipe(stdout_pipe) < 0 || + pipe(stderr_pipe) < 0 || + pipe(stdtst_pipe) < 0) { + return -1; + } + + pid = fork(); + + if (pid == 0) { + close(stdout_pipe[0]); + close(stderr_pipe[0]); + close(stdtst_pipe[0]); + + if (sane_dup2(stdout_pipe[1], 1) < 0 || + sane_dup2(stderr_pipe[1], 2) < 0) { + } + + if (stdout_pipe[1] >= 3) + close(stdout_pipe[1]); + if (stderr_pipe[1] >= 3) + close(stderr_pipe[1]); + return 0; + } else { + priv->pid = pid; + + close(stdout_pipe[1]); + close(stderr_pipe[1]); + close(stdtst_pipe[1]); + + while (stdout_pipe[0] >= 0 || + stderr_pipe[0] >= 0 || + stdtst_pipe[0] > 0) { + + if (stdout_pipe[0] >=0 && + !read_from_pipe(proccess, stdout_pipe[0], STDOUT)) { + stdout_pipe[0] = -1; + } + if (stderr_pipe[0] >=0 && + !read_from_pipe(proccess, stderr_pipe[0], STDERR)) { + stderr_pipe[0] = -1; + } + if (stdtst_pipe[0] >=0 && + !read_from_pipe(proccess, stdtst_pipe[0], CUTTER_PIPE)) { + stdtst_pipe[0] = -1; + } + } + + close(stdout_pipe[0]); + close(stderr_pipe[0]); + close(stdtst_pipe[0]); + + return pid; + } +} + +static void +cut_proccess_init (CutProccess *proccess) +{ + CutProccessPrivate *priv = CUT_PROCCESS_GET_PRIVATE(proccess); + + priv->pid = 0; + priv->stdout_string = g_string_new(NULL); + priv->stderr_string = g_string_new(NULL); +} + +static void +dispose (GObject *object) +{ + CutProccessPrivate *priv = CUT_PROCCESS_GET_PRIVATE(object); + + if (priv->pid) { + kill(priv->pid, SIGKILL); + priv->pid = 0; + } + + if (priv->stdout_string) { + g_string_free(priv->stdout_string, TRUE); + priv->stdout_string = NULL; + } + + if (priv->stderr_string) { + g_string_free(priv->stderr_string, TRUE); + priv->stderr_string = NULL; + } + + G_OBJECT_CLASS(cut_proccess_parent_class)->dispose(object); +} + +CutProccess * +cut_proccess_new () +{ + return g_object_new(CUT_TYPE_PROCCESS, + NULL); +} + + +int +cut_proccess_fork (CutProccess *proccess) +{ + return prepare_pipes(proccess); +} + +int +cut_proccess_get_pid (CutProccess *proccess) +{ + return CUT_PROCCESS_GET_PRIVATE(proccess)->pid; +} + +const gchar * +cut_proccess_get_stdout_message (CutProccess *proccess) +{ + CutProccessPrivate *priv = CUT_PROCCESS_GET_PRIVATE(proccess); + + if (priv->stdout_string) + return priv->stdout_string->str; + + return NULL; +} + +const gchar * +cut_proccess_get_stderr_message (CutProccess *proccess) +{ + CutProccessPrivate *priv = CUT_PROCCESS_GET_PRIVATE(proccess); + + if (priv->stderr_string) + return priv->stderr_string->str; + + return NULL; +} + +/* +vi:ts=4:nowrap:ai:expandtab:sw=4 +*/ Added: trunk/cutter/cut-proccess.h =================================================================== --- trunk/cutter/cut-proccess.h (rev 0) +++ trunk/cutter/cut-proccess.h 2008-03-31 01:53:11 UTC (rev 1363) @@ -0,0 +1,65 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2007 Kouhei Sutou <ko...@co...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + +#ifndef __CUT_PROCCESS_H__ +#define __CUT_PROCCESS_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define CUT_TYPE_PROCCESS (cut_proccess_get_type ()) +#define CUT_PROCCESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CUT_TYPE_PROCCESS, CutProccess)) +#define CUT_PROCCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CUT_TYPE_PROCCESS, CutProccessClass)) +#define CUT_IS_PROCCESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CUT_TYPE_PROCCESS)) +#define CUT_IS_PROCCESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CUT_TYPE_PROCCESS)) +#define CUT_PROCCESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), CUT_TYPE_PROCCESS, CutProccessClass)) + +typedef struct _CutProccess CutProccess; +typedef struct _CutProccessClass CutProccessClass; + +struct _CutProccess +{ + GObject object; +}; + +struct _CutProccessClass +{ + GObjectClass parent_class; +}; + +GType cut_proccess_get_type (void) G_GNUC_CONST; + +CutProccess *cut_proccess_new (void); +int cut_proccess_fork (CutProccess *proccess); +int cut_proccess_get_pid (CutProccess *proccess); +const gchar *cut_proccess_get_stdout_message + (CutProccess *proccess); +const gchar *cut_proccess_get_stderr_message + (CutProccess *proccess); + +G_END_DECLS + +#endif /* __CUT_PROCCESS_H__ */ + +/* +vi:ts=4:nowrap:ai:expandtab:sw=4 +*/ Modified: trunk/cutter/cut-test-context.c =================================================================== --- trunk/cutter/cut-test-context.c 2008-03-31 01:04:27 UTC (rev 1362) +++ trunk/cutter/cut-test-context.c 2008-03-31 01:53:11 UTC (rev 1363) @@ -27,14 +27,12 @@ #include <string.h> #include <setjmp.h> #include <sys/types.h> -#include <signal.h> -#include <unistd.h> -#include <errno.h> #include <glib.h> #include "cut-test-context.h" #include "cut-test-suite.h" #include "cut-test-result.h" +#include "cut-proccess.h" #define CUT_TEST_CONTEXT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CUT_TYPE_TEST_CONTEXT, CutTestContextPrivate)) @@ -49,7 +47,7 @@ GList *taken_strings; gpointer user_data; GDestroyNotify user_data_destroy_notify; - GArray *forks; + GList *proccesses; }; enum @@ -124,20 +122,10 @@ priv->user_data = NULL; priv->user_data_destroy_notify = NULL; - priv->forks = g_array_new(FALSE, FALSE, sizeof(gint)); + priv->proccesses = NULL; } static void -close_all_pids (GArray *forks) -{ - gint i; - - for (i = 0; i < forks->len; i++) { - kill(g_array_index(forks, gint, i), SIGKILL); - } -} - -static void dispose (GObject *object) { CutTestContextPrivate *priv = CUT_TEST_CONTEXT_GET_PRIVATE(object); @@ -157,10 +145,10 @@ priv->test = NULL; } - if (priv->forks) { - close_all_pids(priv->forks); - g_array_free(priv->forks, TRUE); - priv->forks = NULL; + if (priv->proccesses) { + g_list_foreach(priv->proccesses, (GFunc)g_object_unref, NULL); + g_list_free(priv->proccesses); + priv->proccesses = NULL; } g_list_foreach(priv->taken_strings, (GFunc)g_free, NULL); @@ -441,66 +429,61 @@ g_string_free(inspected, FALSE)); } - -static int -sane_dup2 (int fd1, int fd2) -{ - int ret; - do - ret = dup2 (fd1, fd2); - while (ret < 0 && errno == EINTR); - return ret; -} - int cut_test_context_trap_fork (CutTestContext *context, unsigned int time_out) { - CutTestContextPrivate *priv = CUT_TEST_CONTEXT_GET_PRIVATE(context); - pid_t pid; + CutProccess *proccess; + int pid; - int stdout_pipe[2] = { -1, -1 }; - int stderr_pipe[2] = { -1, -1 }; - int stdtst_pipe[2] = { -1, -1 }; + proccess = cut_proccess_new(); - if (pipe(stdout_pipe) < 0 || - pipe(stderr_pipe) < 0 || - pipe(stdtst_pipe) < 0) { - return -1; + pid = cut_proccess_fork(proccess); + + return pid; +} + +static CutProccess * +get_proccess_from_pid (CutTestContext *context, int pid) +{ + GList *node; + CutTestContextPrivate *priv = CUT_TEST_CONTEXT_GET_PRIVATE(context); + + for (node = priv->proccesses; node; node = g_list_next(node)) { + CutProccess *proccess = CUT_PROCCESS(node->data); + if (pid == cut_proccess_get_pid(proccess)) + return proccess; } - pid = fork(); - if (pid < 0) - return -1; + return NULL; +} - if (pid == 0) { - int fd0 = -1; - close(stdout_pipe[0]); - close(stderr_pipe[0]); - close(stdtst_pipe[0]); +const char * +cut_test_context_get_forked_stdout_message (CutTestContext *context, + int pid) +{ + CutProccess *proccess; - if (sane_dup2(stdout_pipe[1], 1) < 0 || - sane_dup2(stderr_pipe[1], 2) < 0 || - (fd0 >= 0 && sane_dup2(fd0, 0) < 0)) { - } + proccess = get_proccess_from_pid(context, pid); + if (proccess) + return cut_proccess_get_stdout_message(proccess); - if (fd0 >= 3) - close(fd0); - if (stdout_pipe[1] >= 3) - close(stdout_pipe[1]); - if (stderr_pipe[1] >= 3) - close(stderr_pipe[1]); - return 0; - } else { - g_array_append_val(priv->forks, pid); + return NULL; +} - close(stdout_pipe[1]); - close(stderr_pipe[1]); - close(stdtst_pipe[1]); - return pid; - } +const char * +cut_test_context_get_forked_stderr_message (CutTestContext *context, + int pid) +{ + CutProccess *proccess; + + proccess = get_proccess_from_pid(context, pid); + if (proccess) + return cut_proccess_get_stdout_message(proccess); + + return NULL; } - + /* vi:ts=4:nowrap:ai:expandtab:sw=4 */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |