Make the 'init <CMD | RUNLEVEL>' commands synchronous.

When a user changes runlevel, or wants to reload the config, we want the
command to return only when the operation has completed.  For instance,
rolling in a new system configuration in runlevel 1 requires that we are
sure we've actually entered that runlevel before rolling it in.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2015-04-25 10:17:46 +02:00
parent 56292f27c2
commit 71ecead5b7
3 changed files with 36 additions and 8 deletions
+13 -4
View File
@@ -84,6 +84,8 @@ static int client(int argc, char *argv[])
{
int fd;
int c;
int result = -1;
ssize_t len;
struct option long_options[] = {
{"debug", 0, NULL, 'd'},
{"help", 0, NULL, 'h'},
@@ -94,7 +96,7 @@ static int client(int argc, char *argv[])
.cmd = 0
};
while ((c = getopt_long (argc, argv, "h?d", long_options, NULL)) != EOF) {
while ((c = getopt_long(argc, argv, "h?d", long_options, NULL)) != EOF) {
switch(c) {
case 'd':
rq.cmd = INIT_CMD_DEBUG;
@@ -123,15 +125,22 @@ static int client(int argc, char *argv[])
return 1;
}
fd = open(FINIT_FIFO, O_WRONLY);
fd = open(FINIT_FIFO, O_RDWR);
if (-1 == fd) {
perror("Failed opening " FINIT_FIFO);
return 1;
}
write(fd, &rq, sizeof(rq));
len = write(fd, &rq, sizeof(rq));
if (len == sizeof(rq)) {
len = read(fd, &rq, sizeof(rq));
if (len == sizeof(rq) && rq.cmd == INIT_CMD_ACK)
result = 0;
}
close(fd);
return 0;
return result;
}
static void banner(void)
+1
View File
@@ -76,6 +76,7 @@
#define INIT_MAGIC 0x03091969
#define INIT_CMD_RUNLVL 1
#define INIT_CMD_DEBUG 2
#define INIT_CMD_ACK 255
struct init_request {
int magic; /* Magic number */
+22 -4
View File
@@ -45,7 +45,7 @@ static plugin_t plugin = {
static void fifo_open(void)
{
plugin.io.fd = open(FINIT_FIFO, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
plugin.io.fd = open(FINIT_FIFO, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (-1 == plugin.io.fd) {
_e("Failed opening %s FIFO, error %d: %s", FINIT_FIFO, errno, strerror(errno));
return;
@@ -85,7 +85,8 @@ static void parse(void *UNUSED(arg), int fd, int UNUSED(events))
}
_d("Magic OK ...");
if (rq.cmd == INIT_CMD_RUNLVL) {
switch (rq.cmd) {
case INIT_CMD_RUNLVL:
switch (rq.runlevel) {
case '0':
_d("Halting system (SIGUSR2)");
@@ -113,13 +114,30 @@ static void parse(void *UNUSED(arg), int fd, int UNUSED(events))
_d("Unsupported runlevel: %d", rq.runlevel);
break;
}
} else if (rq.cmd == INIT_CMD_DEBUG) {
break;
case INIT_CMD_DEBUG:
debug = !debug;
} else {
break;
case INIT_CMD_ACK:
_d("Client failed reading ACK.");
goto leave;
default:
_d("Unsupported cmd: %d", rq.cmd);
break;
}
rq.cmd = INIT_CMD_ACK;
len = write(fd, &rq, sizeof(rq));
if (len != sizeof(rq))
_d("Failed sending ACK back to client.");
else
sleep(1); /* Give client time to read FIFO */
}
leave:
close(fd);
fifo_open();
}