2
* Copyright 2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3, as published
6
* by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranties of
10
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
* PURPOSE. See the GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License along
14
* with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Ted Gould <ted.gould@canonical.com>
20
#include "recoverable-problem.h"
21
#include <glib/gstdio.h>
25
/* Helpers to ensure we write nicely */
32
res = write (fd, string, strlen (string));
33
while (G_UNLIKELY (res == -1 && errno == EINTR));
36
/* Make NULLs fast and fun! */
42
res = write (fd, "", 1);
43
while (G_UNLIKELY (res == -1 && errno == EINTR));
48
apport_child_watch (GPid pid, gint status, gpointer user_data)
50
g_main_loop_quit((GMainLoop *)user_data);
55
apport_child_timeout (gpointer user_data)
57
g_warning("Recoverable Error Reporter Timeout");
58
g_main_loop_quit((GMainLoop *)user_data);
62
/* Code to report an error */
64
report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, const gchar * additional_properties[])
66
GError * error = NULL;
69
gchar * pid_str = NULL;
71
gchar * argv_nopid[2] = {
72
"/usr/share/apport/recoverable_problem",
75
gchar * argv_pid[4] = {
76
"/usr/share/apport/recoverable_problem",
78
NULL, /* put pid_str when allocated here */
83
argv = (gchar **)argv_nopid;
85
if (report_pid != 0) {
86
pid_str = g_strdup_printf("%d", report_pid);
87
argv_pid[2] = pid_str;
88
argv = (gchar**)argv_pid;
91
GSpawnFlags flags = G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
93
flags |= G_SPAWN_DO_NOT_REAP_CHILD;
96
g_spawn_async_with_pipes(NULL, /* cwd */
100
NULL, NULL, /* child setup func */
108
g_warning("Unable to report a recoverable error: %s", error->message);
112
gboolean first = TRUE;
114
if (error_stdin != 0 && signature != NULL) {
115
write_string(error_stdin, "DuplicateSignature");
116
write_null(error_stdin);
117
write_string(error_stdin, signature);
122
if (error_stdin != 0 && additional_properties != NULL) {
124
for (i = 0; additional_properties[i] != NULL; i++) {
126
write_null(error_stdin);
131
write_string(error_stdin, additional_properties[i]);
135
if (error_stdin != 0) {
139
if (wait && pid != 0) {
140
GSource * child_source, * timeout_source;
141
GMainContext * context = g_main_context_new();
142
GMainLoop * loop = g_main_loop_new(context, FALSE);
144
child_source = g_child_watch_source_new(pid);
145
g_source_attach(child_source, context);
146
g_source_set_callback(child_source, (GSourceFunc)apport_child_watch, loop, NULL);
148
timeout_source = g_timeout_source_new_seconds(5);
149
g_source_attach(timeout_source, context);
150
g_source_set_callback(timeout_source, apport_child_timeout, loop, NULL);
152
g_main_loop_run(loop);
154
g_source_destroy(timeout_source);
155
g_source_destroy(child_source);
156
g_main_loop_unref(loop);
157
g_main_context_unref(context);
159
g_spawn_close_pid(pid);