mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
1) make xenconsoled exit gracefully if xcs dies 2) daemonize xenstored before binding to xenstored socket 3) wait to close stdio in xenstored until we're ready to accept connections (so that PID=`xenstored --output-pid` doesn't return until it's ready to accept connections) 4) updates tools/misc/xend for these changes Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Rusty Russell <rusty@rustycorp.com.au> Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
254 lines
5.1 KiB
C
254 lines
5.1 KiB
C
/*\
|
|
* Copyright (C) International Business Machines Corp., 2005
|
|
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
|
*
|
|
* Xen Console Daemon
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; under version 2 of the License.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU 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
|
|
\*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <getopt.h>
|
|
#include <stdbool.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <string.h>
|
|
|
|
#include "xc.h"
|
|
#include "xen/io/domain_controller.h"
|
|
#include "xcs_proto.h"
|
|
|
|
#include "utils.h"
|
|
|
|
struct xs_handle *xs;
|
|
int xc;
|
|
|
|
int xcs_ctrl_fd = -1;
|
|
int xcs_data_fd = -1;
|
|
|
|
bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
|
|
{
|
|
size_t offset = 0;
|
|
ssize_t len;
|
|
|
|
while (offset < size) {
|
|
if (do_read) {
|
|
len = read(fd, data + offset, size - offset);
|
|
} else {
|
|
len = write(fd, data + offset, size - offset);
|
|
}
|
|
|
|
if (len < 1) {
|
|
if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
|
|
continue;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
offset += len;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static int open_domain_socket(const char *path)
|
|
{
|
|
struct sockaddr_un addr;
|
|
int sock;
|
|
size_t addr_len;
|
|
|
|
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
|
|
goto out;
|
|
}
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
strcpy(addr.sun_path, path);
|
|
addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
|
|
|
|
if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
|
|
goto out_close_sock;
|
|
}
|
|
|
|
return sock;
|
|
|
|
out_close_sock:
|
|
close(sock);
|
|
out:
|
|
return -1;
|
|
}
|
|
|
|
static void child_exit(int sig)
|
|
{
|
|
while (waitpid(-1, NULL, WNOHANG) > 0);
|
|
}
|
|
|
|
void daemonize(const char *pidfile)
|
|
{
|
|
pid_t pid;
|
|
int fd;
|
|
int len;
|
|
int i;
|
|
char buf[100];
|
|
|
|
if (getppid() == 1) {
|
|
return;
|
|
}
|
|
|
|
if ((pid = fork()) > 0) {
|
|
exit(0);
|
|
} else if (pid == -1) {
|
|
err(errno, "fork() failed");
|
|
}
|
|
|
|
setsid();
|
|
|
|
/* redirect fd 0,1,2 to /dev/null */
|
|
if ((fd = open("/dev/null",O_RDWR)) == -1) {
|
|
exit(1);
|
|
}
|
|
|
|
for (i = 0; i <= 2; i++) {
|
|
close(i);
|
|
dup2(fd, i);
|
|
}
|
|
|
|
close(fd);
|
|
|
|
umask(027);
|
|
chdir("/");
|
|
|
|
fd = open(pidfile, O_RDWR | O_CREAT);
|
|
if (fd == -1) {
|
|
exit(1);
|
|
}
|
|
|
|
if (lockf(fd, F_TLOCK, 0) == -1) {
|
|
exit(1);
|
|
}
|
|
|
|
len = sprintf(buf, "%d\n", getpid());
|
|
write(fd, buf, len);
|
|
|
|
signal(SIGCHLD, child_exit);
|
|
signal(SIGTSTP, SIG_IGN);
|
|
signal(SIGTTOU, SIG_IGN);
|
|
signal(SIGTTIN, SIG_IGN);
|
|
}
|
|
|
|
/* synchronized send/recv strictly for setting up xcs */
|
|
/* always use asychronize callbacks any other time */
|
|
static bool xcs_send_recv(int fd, xcs_msg_t *msg)
|
|
{
|
|
bool ret = false;
|
|
|
|
if (!write_sync(fd, msg, sizeof(*msg))) {
|
|
dolog(LOG_ERR, "Write failed at %s:%s():L%d? Possible bug.",
|
|
__FILE__, __FUNCTION__, __LINE__);
|
|
goto out;
|
|
}
|
|
|
|
if (!read_sync(fd, msg, sizeof(*msg))) {
|
|
dolog(LOG_ERR, "Read failed at %s:%s():L%d? Possible bug.",
|
|
__FILE__, __FUNCTION__, __LINE__);
|
|
goto out;
|
|
}
|
|
|
|
ret = true;
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
bool xen_setup(void)
|
|
{
|
|
int sock;
|
|
xcs_msg_t msg;
|
|
|
|
xs = xs_daemon_open();
|
|
if (xs == NULL) {
|
|
dolog(LOG_ERR,
|
|
"Failed to contact xenstore (%m). Is it running?");
|
|
goto out;
|
|
}
|
|
|
|
xc = xc_interface_open();
|
|
if (xc == -1) {
|
|
dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
|
|
goto out;
|
|
}
|
|
|
|
sock = open_domain_socket(XCS_SUN_PATH);
|
|
if (sock == -1) {
|
|
dolog(LOG_ERR, "Failed to contact xcs (%m). Is it running?");
|
|
goto out_close_store;
|
|
}
|
|
|
|
xcs_ctrl_fd = sock;
|
|
|
|
sock = open_domain_socket(XCS_SUN_PATH);
|
|
if (sock == -1) {
|
|
dolog(LOG_ERR, "Failed to contact xcs (%m). Is it running?");
|
|
goto out_close_ctrl;
|
|
}
|
|
|
|
xcs_data_fd = sock;
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
msg.type = XCS_CONNECT_CTRL;
|
|
if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
|
|
dolog(LOG_ERR, "xcs control connect failed. Possible bug.");
|
|
goto out_close_data;
|
|
}
|
|
|
|
msg.type = XCS_CONNECT_DATA;
|
|
if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
|
|
dolog(LOG_ERR, "xcs data connect failed. Possible bug.");
|
|
goto out_close_data;
|
|
}
|
|
|
|
/* Since the vast majority of control messages are console messages
|
|
it's just easier to ignore other messages that try to bind to
|
|
a specific type. */
|
|
msg.type = XCS_MSG_BIND;
|
|
msg.u.bind.port = PORT_WILDCARD;
|
|
msg.u.bind.type = TYPE_WILDCARD;
|
|
if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
|
|
dolog(LOG_ERR, "xcs vind failed. Possible bug.");
|
|
goto out_close_data;
|
|
}
|
|
|
|
return true;
|
|
|
|
out_close_data:
|
|
close(xcs_ctrl_fd);
|
|
xcs_data_fd = -1;
|
|
out_close_ctrl:
|
|
close(xcs_ctrl_fd);
|
|
xcs_ctrl_fd = -1;
|
|
out_close_store:
|
|
xs_daemon_close(xs);
|
|
out:
|
|
return false;
|
|
}
|
|
|