debuggers.hg

view tools/libxl/libxl_exec.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents ca75ceb02221
children
line source
2 /*
3 * Copyright (C) 2009 Citrix Ltd.
4 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
5 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 only. with the special
10 * exception on linking described in file LICENSE.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 */
18 #include "libxl_osdeps.h"
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <assert.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <signal.h> /* for SIGKILL */
30 #include "libxl.h"
31 #include "libxl_internal.h"
33 static int call_waitpid(pid_t (*waitpid_cb)(pid_t, int *, int), pid_t pid, int *status, int options)
34 {
35 return (waitpid_cb) ? waitpid_cb(pid, status, options) : waitpid(pid, status, options);
36 }
38 void libxl__exec(int stdinfd, int stdoutfd, int stderrfd, const char *arg0,
39 char **args)
40 /* call this in the child */
41 {
42 int i;
44 if (stdinfd != -1)
45 dup2(stdinfd, STDIN_FILENO);
46 if (stdoutfd != -1)
47 dup2(stdoutfd, STDOUT_FILENO);
48 if (stderrfd != -1)
49 dup2(stderrfd, STDERR_FILENO);
50 for (i = 4; i < 256; i++)
51 close(i);
53 signal(SIGPIPE, SIG_DFL);
54 /* in case our caller set it to IGN. subprocesses are entitled
55 * to assume they got DFL. */
57 execvp(arg0, args);
58 _exit(-1);
59 }
61 void libxl_report_child_exitstatus(libxl_ctx *ctx,
62 xentoollog_level level,
63 const char *what, pid_t pid, int status)
64 {
66 if (WIFEXITED(status)) {
67 int st = WEXITSTATUS(status);
68 if (st)
69 LIBXL__LOG(ctx, level, "%s [%ld] exited"
70 " with error status %d", what, (unsigned long)pid, st);
71 else
72 LIBXL__LOG(ctx, level, "%s [%ld] unexpectedly"
73 " exited status zero", what, (unsigned long)pid);
74 } else if (WIFSIGNALED(status)) {
75 int sig = WTERMSIG(status);
76 const char *str = strsignal(sig);
77 const char *coredump = WCOREDUMP(status) ? " (core dumped)" : "";
78 if (str)
79 LIBXL__LOG(ctx, level, "%s [%ld] died due to"
80 " fatal signal %s%s", what, (unsigned long)pid,
81 str, coredump);
82 else
83 LIBXL__LOG(ctx, level, "%s [%ld] died due to unknown"
84 " fatal signal number %d%s", what, (unsigned long)pid,
85 sig, coredump);
86 } else {
87 LIBXL__LOG(ctx, level, "%s [%ld] gave unknown"
88 " wait status 0x%x", what, (unsigned long)pid, status);
89 }
90 }
92 int libxl__spawn_spawn(libxl_ctx *ctx,
93 libxl__device_model_starting *starting,
94 const char *what,
95 void (*intermediate_hook)(void *for_spawn,
96 pid_t innerchild))
97 {
98 pid_t child, got;
99 int status;
100 pid_t intermediate;
101 libxl__spawn_starting *for_spawn = starting->for_spawn;
103 if (for_spawn) {
104 for_spawn->what = strdup(what);
105 if (!for_spawn->what) return ERROR_NOMEM;
106 }
108 intermediate = libxl_fork(ctx);
109 if (intermediate ==-1) {
110 if (for_spawn) free(for_spawn->what);
111 return ERROR_FAIL;
112 }
113 if (intermediate) {
114 /* parent */
115 if (for_spawn) for_spawn->intermediate = intermediate;
116 return 1;
117 }
119 /* we are now the intermediate process */
121 child = fork();
122 if (child == -1)
123 exit(255);
124 if (!child)
125 return 0; /* caller runs child code */
127 intermediate_hook(starting, child);
129 if (!for_spawn) _exit(0); /* just detach then */
131 got = call_waitpid(ctx->waitpid_instead, child, &status, 0);
132 assert(got == child);
134 _exit(WIFEXITED(status) ? WEXITSTATUS(status) :
135 WIFSIGNALED(status) && WTERMSIG(status) < 127
136 ? WTERMSIG(status)+128 : -1);
137 }
139 static void report_spawn_intermediate_status(libxl_ctx *ctx,
140 libxl__spawn_starting *for_spawn,
141 int status)
142 {
143 if (!WIFEXITED(status)) {
144 char *intermediate_what;
145 /* intermediate process did the logging itself if it exited */
146 if ( asprintf(&intermediate_what,
147 "%s intermediate process (startup monitor)",
148 for_spawn->what) < 0 )
149 intermediate_what = "intermediate process (startup monitor)";
150 libxl_report_child_exitstatus(ctx, LIBXL__LOG_ERROR, intermediate_what,
151 for_spawn->intermediate, status);
152 }
153 }
155 int libxl__spawn_detach(libxl_ctx *ctx,
156 libxl__spawn_starting *for_spawn)
157 {
158 int r, status;
159 pid_t got;
160 int rc = 0;
162 if (!for_spawn) return 0;
164 if (for_spawn->intermediate) {
165 r = kill(for_spawn->intermediate, SIGKILL);
166 if (r) {
167 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
168 "could not kill %s intermediate process [%ld]",
169 for_spawn->what,
170 (unsigned long)for_spawn->intermediate);
171 abort(); /* things are very wrong */
172 }
173 got = call_waitpid(ctx->waitpid_instead, for_spawn->intermediate, &status, 0);
174 assert(got == for_spawn->intermediate);
175 if (!(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)) {
176 report_spawn_intermediate_status(ctx, for_spawn, status);
177 rc = ERROR_FAIL;
178 }
179 for_spawn->intermediate = 0;
180 }
182 free(for_spawn->what);
183 for_spawn->what = 0;
185 return rc;
186 }
188 int libxl__spawn_check(libxl_ctx *ctx, void *for_spawn_void)
189 {
190 libxl__spawn_starting *for_spawn = for_spawn_void;
191 pid_t got;
192 int status;
194 if (!for_spawn) return 0;
196 assert(for_spawn->intermediate);
197 got = call_waitpid(ctx->waitpid_instead, for_spawn->intermediate, &status, WNOHANG);
198 if (!got) return 0;
200 assert(got == for_spawn->intermediate);
201 report_spawn_intermediate_status(ctx, for_spawn, status);
203 for_spawn->intermediate = 0;
204 return ERROR_FAIL;
205 }