test: Make nstool hold robust against interruptions to control clients

Currently nstool die()s on essentially any error.  In most cases that's
fine for our purposes.  However, it's a problem when in "hold" mode and
getting an IO error on an accept()ed socket.  This could just indicate that
the control client aborted prematurely, in which case we don't want to
kill of the namespace we're holding.

Adjust these to print an error, close() the control client socket and
carry on.  In addition, we need to explicitly ignore SIGPIPE in order not
to be killed by an abruptly closed client connection.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-11-06 14:03:22 +11:00 committed by Stefano Brivio
parent b456ee1b53
commit 1699083f29

View file

@ -31,10 +31,15 @@
#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0]))) #define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
#define die(...) \ #define die(...) \
do { \ do { \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "nstool: " __VA_ARGS__); \
exit(1); \ exit(1); \
} while (0)
#define err(...) \
do { \
fprintf(stderr, "nstool: " __VA_ARGS__); \
} while (0) } while (0)
struct ns_type { struct ns_type {
@ -156,6 +161,9 @@ static int connect_ctl(const char *sockpath, bool wait,
static void cmd_hold(int argc, char *argv[]) static void cmd_hold(int argc, char *argv[])
{ {
struct sigaction sa = {
.sa_handler = SIG_IGN,
};
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX); int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
struct sockaddr_un addr; struct sockaddr_un addr;
const char *sockpath = argv[1]; const char *sockpath = argv[1];
@ -185,6 +193,10 @@ static void cmd_hold(int argc, char *argv[])
if (!getcwd(info.cwd, sizeof(info.cwd))) if (!getcwd(info.cwd, sizeof(info.cwd)))
die("getcwd(): %s\n", strerror(errno)); die("getcwd(): %s\n", strerror(errno));
rc = sigaction(SIGPIPE, &sa, NULL);
if (rc)
die("sigaction(SIGPIPE): %s\n", strerror(errno));
do { do {
int afd = accept(fd, NULL, NULL); int afd = accept(fd, NULL, NULL);
char buf; char buf;
@ -193,17 +205,21 @@ static void cmd_hold(int argc, char *argv[])
die("accept(): %s\n", strerror(errno)); die("accept(): %s\n", strerror(errno));
rc = write(afd, &info, sizeof(info)); rc = write(afd, &info, sizeof(info));
if (rc < 0) if (rc < 0) {
die("write(): %s\n", strerror(errno)); err("holder write() to control socket: %s\n",
strerror(errno));
}
if ((size_t)rc < sizeof(info)) if ((size_t)rc < sizeof(info))
die("short write() on control socket\n"); err("holder short write() on control socket\n");
rc = read(afd, &buf, sizeof(buf)); rc = read(afd, &buf, sizeof(buf));
if (rc < 0) if (rc < 0) {
die("read(): %s\n", strerror(errno)); err("holder read() on control socket: %s\n",
strerror(errno));
}
close(afd); close(afd);
} while (rc == 0); } while (rc <= 0);
unlink(sockpath); unlink(sockpath);
} }