X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fvlog-socket.c;h=0dc836f53891691514dd0a2d3037ea971f18aaf5;hb=dd373c4f79ecdd78b1b4f2afab86f0ba9bc5eeb4;hp=a9f8a520b36fa6ec2b72456a1b7b10dcf327537b;hpb=5680957f84873e871b99acbef0c9f472b4797dfe;p=sliver-openvswitch.git diff --git a/lib/vlog-socket.c b/lib/vlog-socket.c index a9f8a520b..0dc836f53 100644 --- a/lib/vlog-socket.c +++ b/lib/vlog-socket.c @@ -33,6 +33,7 @@ #include #include "vlog-socket.h" +#include #include #include #include @@ -43,15 +44,19 @@ #include #include #include +#include "daemon.h" #include "fatal-signal.h" #include "poll-loop.h" #include "socket-util.h" +#include "timeval.h" #include "util.h" -#include "vlog.h" #ifndef SCM_CREDENTIALS #include #endif + +#define THIS_MODULE VLM_vlog_socket +#include "vlog.h" /* Server for Vlog control connection. */ struct vlog_server { @@ -74,6 +79,11 @@ static void poll_server(int fd, short int events, void *server_); * - An absolute path (starting with '/') that gives the exact name of * the Unix domain socket to listen on. * + * A program that (optionally) daemonizes itself should call this function + * *after* daemonization, so that the socket name contains the pid of the + * daemon instead of the pid of the program that exited. (Otherwise, "vlogconf + * --target .pid" will fail.) + * * Returns 0 if successful, otherwise a positive errno value. If successful, * sets '*serverp' to the new vlog_server, otherwise to NULL. */ int @@ -91,10 +101,10 @@ vlog_server_listen(const char *path, struct vlog_server **serverp) server->fd = make_unix_socket(SOCK_DGRAM, true, true, server->path, NULL); if (server->fd < 0) { int fd = server->fd; - free(server->path); - free(server); fprintf(stderr, "Could not initialize vlog configuration socket: %s\n", strerror(-server->fd)); + free(server->path); + free(server); if (serverp) { *serverp = NULL; } @@ -212,7 +222,7 @@ recv_with_creds(const struct vlog_server *server, fprintf(stderr, "vlog: config message not from a socket\n"); return -1; } - recent = time(0) - 30; + recent = time_now() - 30; if (s.st_atime < recent || s.st_ctime < recent || s.st_mtime < recent) { fprintf(stderr, "vlog: config socket too old\n"); return -1; @@ -255,6 +265,12 @@ poll_server(int fd UNUSED, short int events, void *server_) reply = msg ? msg : xstrdup("ack"); } else if (!strcmp(cmd_buf, "list")) { reply = vlog_get_levels(); + } else if (!strcmp(cmd_buf, "reopen")) { + int error = vlog_reopen_log_file(); + reply = (error + ? xasprintf("could not reopen log file \"%s\": %s", + vlog_get_log_file(), strerror(error)) + : xstrdup("ack")); } else { reply = xstrdup("nak"); } @@ -273,40 +289,72 @@ struct vlog_client { int fd; }; -/* Connects to a Vlog server socket. If 'path' does not start with '/', then - * it start with a PID as a string. If a non-null, non-absolute name was - * passed to Vlog_server_socket::listen(), then it must follow the PID in - * 'path'. If 'path' starts with '/', then it must be an absolute path that - * gives the exact name of the Unix domain socket to connect to. +/* Connects to a Vlog server socket. 'path' may be: + * + * - A string that starts with a PID. If a non-null, non-absolute name + * was passed to Vlog_server_socket::listen(), then it must follow the + * PID in 'path'. + * + * - An absolute path (starting with '/') to a Vlog server socket or a + * pidfile. If it is a pidfile, the pidfile will be read and translated + * into a Vlog server socket file name. + * + * - A relative path, which is translated into a pidfile name and then + * treated as above. * * Returns 0 if successful, otherwise a positive errno value. If successful, * sets '*clientp' to the new vlog_client, otherwise to NULL. */ int vlog_client_connect(const char *path, struct vlog_client **clientp) { + static int counter; struct vlog_client *client; - int fd; + struct stat s; + int error; client = xmalloc(sizeof *client); - client->connect_path = (path[0] == '/' - ? xstrdup(path) - : xasprintf("/tmp/vlogs.%s", path)); - - client->bind_path = xasprintf("/tmp/vlog.%ld", (long int) getpid()); - fd = make_unix_socket(SOCK_DGRAM, false, false, - client->bind_path, client->connect_path); - - if (fd >= 0) { - client->fd = fd; - *clientp = client; - return 0; + if (path[0] == '/') { + client->connect_path = xstrdup(path); + } else if (isdigit((unsigned char) path[0])) { + client->connect_path = xasprintf("/tmp/vlogs.%s", path); } else { + client->connect_path = make_pidfile_name(path); + } + client->bind_path = NULL; + + if (stat(client->connect_path, &s)) { + error = errno; + VLOG_WARN("could not stat \"%s\": %s", + client->connect_path, strerror(error)); + goto error; + } else if (S_ISREG(s.st_mode)) { + pid_t pid = read_pidfile(client->connect_path); + if (pid < 0) { + error = -pid; + VLOG_WARN("could not read pidfile \"%s\": %s", + client->connect_path, strerror(error)); + goto error; + } free(client->connect_path); - free(client->bind_path); - free(client); - *clientp = NULL; - return errno; + client->connect_path = xasprintf("/tmp/vlogs.%ld", (long int) pid); + } + client->bind_path = xasprintf("/tmp/vlog.%ld.%d", + (long int) getpid(), counter++); + client->fd = make_unix_socket(SOCK_DGRAM, false, false, + client->bind_path, client->connect_path); + if (client->fd < 0) { + error = -client->fd; + goto error; } + *clientp = client; + return 0; + +error: + free(client->connect_path); + free(client->bind_path); + free(client); + *clientp = NULL; + return error; } /* Destroys 'client'. */ @@ -383,11 +431,11 @@ vlog_client_recv(struct vlog_client *client, char **reply) pfd.fd = client->fd; pfd.events = POLLIN; - nfds = poll(&pfd, 1, 1000); + nfds = time_poll(&pfd, 1, 1000); if (nfds == 0) { return ETIMEDOUT; } else if (nfds < 0) { - return errno; + return -nfds; } nbytes = read(client->fd, buffer, sizeof buffer - 1); @@ -432,4 +480,3 @@ vlog_client_target(const struct vlog_client *client) { return client->connect_path; } -