Commit de112fd8 authored by Christian Persch's avatar Christian Persch

Der Tod und das Datensichtgerät

https://bugzilla.gnome.org/show_bug.cgi?id=112172

Conflicts:
	src/reaper.c
	src/reaper.h
parent 19e2cbbe
......@@ -66,10 +66,6 @@
<title>Interna</title>
<xi:include href="xml/vte-access.xml"/>
</chapter>
<chapter id="deprecated-objects">
<title>Deprecated</title>
<xi:include href="xml/vte-reaper.xml"/>
</chapter>
</part>
<chapter id="object-hierarchy">
......
......@@ -227,20 +227,3 @@ VteTerminalAccessibleFactory
VteTerminalAccessibleFactoryClass
vte_terminal_accessible_factory_new
</SECTION>
<SECTION>
<FILE>vte-reaper</FILE>
<TITLE>VteReaper</TITLE>
VteReaper
vte_reaper_add_child
vte_reaper_get
<SUBSECTION Standard>
VTE_IS_REAPER
VTE_IS_REAPER_CLASS
VTE_REAPER
VTE_REAPER_CLASS
VTE_REAPER_GET_CLASS
VTE_TYPE_REAPER
vte_reaper_get_type
</SECTION>
......@@ -7,10 +7,8 @@
#include "vteaccess.h"
#include "vtepty.h"
#include "vtetypebuiltins.h"
#include "reaper.h"
vte_pty_get_type
vte_reaper_get_type
vte_terminal_get_type
vte_terminal_accessible_get_type
vte_terminal_accessible_factory_get_type
......
......@@ -5,7 +5,7 @@ EXTRA_DIST = iso2022.txt
# The library
headerdir = $(includedir)/vte-$(VTE_API_VERSION)/vte
header_HEADERS = reaper.h vte.h vteaccess.h vtepty.h vtetypebuiltins.h vteversion.h vtedeprecated.h
header_HEADERS = vte.h vteaccess.h vtepty.h vtetypebuiltins.h vteversion.h vtedeprecated.h
lib_LTLIBRARIES = libvte-@VTE_API_MAJOR_VERSION@.@VTE_API_MINOR_VERSION@.la
......@@ -44,8 +44,6 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_SOURCES = \
matcher.c \
matcher.h \
pty.c \
reaper.c \
reaper.h \
ring.c \
ring.h \
table.c \
......@@ -105,7 +103,7 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_LIBADD = $(VTE_LIBS)
libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_LDFLAGS = \
$(VTE_LDFLAGS) \
-version-info $(LT_VERSION_INFO) \
-export-symbols-regex "^vte_terminal_.*|^vte_pty_.*|^vte_get_.*|^vte_reaper_.*|_vte_debug_.*" \
-export-symbols-regex "^vte_terminal_.*|^vte_pty_.*|^vte_get_.*|_vte_debug_.*" \
@LIBTOOL_EXPORT_OPTIONS@ @LIBTOOL_FLAGS@ \
$(AM_LDFLAGS)
......@@ -223,7 +221,7 @@ TEST_SH = \
$(NULL)
EXTRA_DIST += $(TEST_SH)
check_PROGRAMS = dumpkeys iso2022 reaper reflect-text-view reflect-vte mev ssfe table trie xticker vteconv vtetc
check_PROGRAMS = dumpkeys iso2022 reflect-text-view reflect-vte mev ssfe table trie xticker vteconv vtetc
TESTS = table trie $(TEST_SH)
AM_CFLAGS = $(GLIB_CFLAGS)
......@@ -338,9 +336,6 @@ trie_LDADD = $(VTE_LIBS)
vtetc_SOURCES = vtetc.c vtetc.h debug.c debug.h
vtetc_CPPFLAGS = -DTERMCAP_MAIN
reaper_SOURCES = reaper.c reaper.h debug.c debug.h marshal.c marshal.h
reaper_CPPFLAGS = -DREAPER_MAIN -DLOCALEDIR='"$(localedir)"'
vteconv_SOURCES = buffer.h debug.c debug.h vteconv.c vteconv.h
vteconv_CPPFLAGS = -DVTECONV_MAIN
vteconv_CFLAGS = $(VTE_CFLAGS)
......
/*
* Copyright (C) 2002 Red Hat, Inc.
*
* 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.1 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* SECTION: vte-reaper
* @short_description: A singleton object which catches %SIGCHLD signals and
* converts them into GObject-style &quot;child-exited&quot; signals
*
* Because an application may need to be notified when child processes
* exit, and because there is only one %SIGCHLD handler, the #VteTerminal
* widget relies on a #VteReaper to watch for %SIGCHLD notifications and
* retrieve the exit status of child processes which have exited. When
* glib provides child_watch functionality, the #VteReaper merely acts as
* a proxy for glib's own functionality.
*
* Since 0.11.11
*/
#include <config.h>
#include "debug.h"
#include "marshal.h"
#include "reaper.h"
static VteReaper *singleton_reaper = NULL;
G_DEFINE_TYPE(VteReaper, vte_reaper, G_TYPE_OBJECT)
static void
vte_reaper_child_watch_cb(GPid pid, gint status, gpointer data)
{
_vte_debug_print(VTE_DEBUG_SIGNALS,
"Reaper emitting child-exited signal.\n");
g_signal_emit_by_name(data, "child-exited", pid, status);
g_spawn_close_pid (pid);
}
/**
* vte_reaper_add_child:
* @pid: the ID of a child process which will be monitored
*
* Ensures that child-exited signals will be emitted when @pid exits. This is
* necessary for correct operation when running with glib versions >= 2.4.
*
* Returns: the new source ID
*
* Since 0.11.11
*/
int
vte_reaper_add_child(GPid pid)
{
return g_child_watch_add_full(G_PRIORITY_LOW,
pid,
vte_reaper_child_watch_cb,
vte_reaper_get(),
(GDestroyNotify)g_object_unref);
}
static void
vte_reaper_init(VteReaper *reaper)
{
}
static GObject*
vte_reaper_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
if (singleton_reaper) {
return g_object_ref (singleton_reaper);
} else {
GObject *obj;
obj = G_OBJECT_CLASS (vte_reaper_parent_class)->constructor (type, n_construct_properties, construct_properties);
singleton_reaper = VTE_REAPER (obj);
return obj;
}
}
static void
vte_reaper_finalize(GObject *reaper)
{
G_OBJECT_CLASS(vte_reaper_parent_class)->finalize(reaper);
singleton_reaper = NULL;
}
static void
vte_reaper_class_init(VteReaperClass *klass)
{
GObjectClass *gobject_class;
/**
* VteReaper::child-exited:
* @vtereaper: the object which received the signal
* @arg1: the process ID of the exited child
* @arg2: the status of the exited child, as returned by waitpid()
*
* Emitted when the #VteReaper object detects that a child of the
* current process has exited.
*
* Since: 0.11.11
*/
klass->child_exited_signal = g_signal_new(g_intern_static_string("child-exited"),
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
_vte_marshal_VOID__INT_INT,
G_TYPE_NONE,
2, G_TYPE_INT, G_TYPE_INT);
gobject_class = G_OBJECT_CLASS(klass);
gobject_class->constructor = vte_reaper_constructor;
gobject_class->finalize = vte_reaper_finalize;
}
/**
* vte_reaper_get:
*
* Finds the address of the global #VteReaper object, creating the object if
* necessary.
*
* Returns: the global #VteReaper object, which should not be unreffed.
*/
VteReaper *
vte_reaper_get(void)
{
return g_object_new(VTE_TYPE_REAPER, NULL);
}
#ifdef REAPER_MAIN
#include <unistd.h>
GMainContext *context;
GMainLoop *loop;
pid_t child;
static void
child_exited(GObject *object, int pid, int status, gpointer data)
{
g_print("[parent] Child with pid %d exited with code %d, "
"was waiting for %d.\n", pid, status, GPOINTER_TO_INT(data));
if (child == pid) {
g_print("[parent] Quitting.\n");
g_main_loop_quit(loop);
}
}
int
main(int argc, char **argv)
{
VteReaper *reaper;
pid_t p, q;
_vte_debug_init();
g_type_init();
context = g_main_context_default();
loop = g_main_loop_new(context, FALSE);
reaper = vte_reaper_get();
g_print("[parent] Forking.\n");
p = fork();
switch (p) {
case -1:
g_print("[parent] Fork failed.\n");
g_assert_not_reached();
break;
case 0:
g_print("[child] Going to sleep.\n");
sleep(10);
g_print("[child] Quitting.\n");
_exit(30);
break;
default:
g_print("[parent] Starting to wait for %d.\n", p);
child = p;
g_signal_connect(reaper,
"child-exited",
G_CALLBACK(child_exited),
GINT_TO_POINTER(child));
break;
}
g_print("[parent] Forking.\n");
q = fork();
switch (q) {
case -1:
g_print("[parent] Fork failed.\n");
g_assert_not_reached();
break;
case 0:
g_print("[child] Going to sleep.\n");
sleep(5);
_exit(5);
break;
default:
g_print("[parent] Not waiting for %d.\n", q);
break;
}
g_main_loop_run(loop);
g_object_unref(reaper);
return 0;
}
#endif
/*
* Copyright (C) 2002 Red Hat, Inc.
*
* 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.1 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VTE_DISABLE_DEPRECATED
#ifndef vte_reaper_h_included
#define vte_reaper_h_included
#include <sys/wait.h>
#include <signal.h>
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
/**
* VteReaper:
*
* The reaper object.
*/
struct _VteReaper {
GObject object;
/*< private >*/
GIOChannel *_channel; /* unused */
int _iopipe[2]; /* unused */
};
typedef struct _VteReaper VteReaper;
struct _VteReaperClass {
GObjectClass parent_class;
/*< private >*/
guint child_exited_signal;
};
typedef struct _VteReaperClass VteReaperClass;
GType vte_reaper_get_type(void);
#define VTE_TYPE_REAPER (vte_reaper_get_type())
#define VTE_REAPER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
VTE_TYPE_REAPER, \
VteReaper))
#define VTE_REAPER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), \
VTE_TYPE_REAPER, \
VteReaperClass)
#define VTE_IS_REAPER(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), VTE_TYPE_REAPER)
#define VTE_IS_REAPER_CLASS(klass) G_TYPE_CHECK_CLASS_TYPE((klass), \
VTE_TYPE_REAPER)
#define VTE_REAPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
VTE_TYPE_REAPER, \
VteReaperClass))
VteReaper *vte_reaper_get(void);
int vte_reaper_add_child(GPid pid);
G_END_DECLS
#endif
#endif /* !VTE_DISABLE_DEPRECATED */
......@@ -46,7 +46,6 @@
#include "debug.h"
#include "vteconv.h"
#include "vtedraw.h"
#include "reaper.h"
#include "ring.h"
#include "caps.h"
......@@ -200,7 +199,7 @@ struct _VteTerminalPrivate {
guint pty_output_source;
gboolean pty_input_active;
GPid pty_pid; /* pid of child using pty slave */
VteReaper *pty_reaper;
guint child_watch_source;
int child_exit_status;
/* Input data queues. */
......
......@@ -3215,11 +3215,10 @@ not_inserted:
return line_wrapped;
}
/* Catch a VteReaper child-exited signal, and if it matches the one we're
* looking for, emit one of our own. */
static void
vte_terminal_catch_child_exited(VteReaper *reaper, int pid, int status,
VteTerminal *terminal)
vte_terminal_child_watch_cb(GPid pid,
int status,
VteTerminal *terminal)
{
if (pid == terminal->pvt->pty_pid) {
GObject *object = G_OBJECT(terminal);
......@@ -3240,14 +3239,8 @@ vte_terminal_catch_child_exited(VteReaper *reaper, int pid, int status,
}
#endif
}
/* Disconnect from the reaper. */
if (terminal->pvt->pty_reaper != NULL) {
g_signal_handlers_disconnect_by_func(terminal->pvt->pty_reaper,
vte_terminal_catch_child_exited,
terminal);
g_object_unref(terminal->pvt->pty_reaper);
terminal->pvt->pty_reaper = NULL;
}
terminal->pvt->child_watch_source = 0;
terminal->pvt->pty_pid = -1;
/* Close out the PTY. */
......@@ -3402,7 +3395,6 @@ vte_terminal_watch_child (VteTerminal *terminal,
{
VteTerminalPrivate *pvt;
GObject *object;
VteReaper *reaper;
g_return_if_fail(VTE_IS_TERMINAL(terminal));
g_return_if_fail(child_pid != -1);
......@@ -3421,22 +3413,14 @@ vte_terminal_watch_child (VteTerminal *terminal,
pvt->child_exit_status = 0;
/* Catch a child-exited signal from the child pid. */
reaper = vte_reaper_get();
vte_reaper_add_child(child_pid);
if (reaper != pvt->pty_reaper) {
if (terminal->pvt->pty_reaper != NULL) {
g_signal_handlers_disconnect_by_func(pvt->pty_reaper,
vte_terminal_catch_child_exited,
terminal);
g_object_unref(pvt->pty_reaper);
}
g_signal_connect(reaper, "child-exited",
G_CALLBACK(vte_terminal_catch_child_exited),
terminal);
pvt->pty_reaper = reaper;
} else {
g_object_unref(reaper);
}
if (terminal->pvt->child_watch_source != 0) {
g_source_remove (terminal->pvt->child_watch_source);
}
terminal->pvt->child_watch_source =
g_child_watch_add_full(G_PRIORITY_HIGH,
child_pid,
(GChildWatchFunc)vte_terminal_child_watch_cb,
terminal, NULL);
/* FIXMEchpe: call vte_terminal_set_size here? */
......@@ -8852,12 +8836,10 @@ vte_terminal_finalize(GObject *object)
}
/* Stop listening for child-exited signals. */
if (terminal->pvt->pty_reaper != NULL) {
g_signal_handlers_disconnect_by_func(terminal->pvt->pty_reaper,
vte_terminal_catch_child_exited,
terminal);
g_object_unref(terminal->pvt->pty_reaper);
}
if (terminal->pvt->child_watch_source != 0) {
g_source_remove (terminal->pvt->child_watch_source);
terminal->pvt->child_watch_source = 0;
}
/* Stop processing input. */
vte_terminal_stop_processing (terminal);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment