mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-09 15:18:09 +01:00
3c6eec87e3
This is a bit messier than I'd like, but we want to clearly remove all dev code (not just have it uncalled), so we remove fields and functions altogether rather than stub them out. This means we put #ifdefs in callers in some places, but at least it's explicit. We still run tests, but only a subset, and we run with NO_VALGRIND under Travis to avoid increasing test times too much. See-also: #176 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
137 lines
3.2 KiB
C
137 lines
3.2 KiB
C
#include <assert.h>
|
|
#include <ccan/err/err.h>
|
|
#include <ccan/str/str.h>
|
|
#include <common/dev_disconnect.h>
|
|
#include <common/status.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <wire/gen_peer_wire.h>
|
|
|
|
#if DEVELOPER
|
|
/* We move the fd IFF we do a disconnect. */
|
|
static int dev_disconnect_fd = -1;
|
|
static char dev_disconnect_line[200];
|
|
static int dev_disconnect_count, dev_disconnect_len;
|
|
static bool dev_disconnect_nocommit;
|
|
|
|
bool dev_suppress_commit;
|
|
|
|
static void next_dev_disconnect(void)
|
|
{
|
|
int r;
|
|
char *asterisk;
|
|
|
|
r = read(dev_disconnect_fd,
|
|
dev_disconnect_line, sizeof(dev_disconnect_line)-1);
|
|
if (r < 0)
|
|
err(1, "Reading dev_disconnect file");
|
|
lseek(dev_disconnect_fd, -r, SEEK_CUR);
|
|
|
|
/* Get first line */
|
|
dev_disconnect_line[r] = '\n';
|
|
dev_disconnect_len = strcspn(dev_disconnect_line, "\n");
|
|
dev_disconnect_line[dev_disconnect_len] = '\0';
|
|
if (strends(dev_disconnect_line, "-nocommit")) {
|
|
dev_disconnect_line[strlen(dev_disconnect_line)
|
|
- strlen("-nocommit")] = '\0';
|
|
dev_disconnect_nocommit = true;
|
|
} else
|
|
dev_disconnect_nocommit = false;
|
|
|
|
asterisk = strchr(dev_disconnect_line, '*');
|
|
if (asterisk) {
|
|
dev_disconnect_count = atoi(asterisk+1);
|
|
if (dev_disconnect_count < 1)
|
|
errx(1, "dev_disconnect invalid count: %s",
|
|
dev_disconnect_line);
|
|
*asterisk = '\0';
|
|
} else
|
|
dev_disconnect_count = 1;
|
|
}
|
|
|
|
void dev_disconnect_init(int fd)
|
|
{
|
|
/* So we can move forward if we do use the line. */
|
|
dev_disconnect_fd = fd;
|
|
}
|
|
|
|
enum dev_disconnect dev_disconnect(int pkt_type)
|
|
{
|
|
if (dev_disconnect_fd == -1)
|
|
return DEV_DISCONNECT_NORMAL;
|
|
|
|
if (!dev_disconnect_count)
|
|
next_dev_disconnect();
|
|
|
|
if (!streq(wire_type_name(pkt_type), dev_disconnect_line+1))
|
|
return DEV_DISCONNECT_NORMAL;
|
|
|
|
if (--dev_disconnect_count != 0) {
|
|
return DEV_DISCONNECT_NORMAL;
|
|
}
|
|
|
|
lseek(dev_disconnect_fd, dev_disconnect_len+1, SEEK_CUR);
|
|
|
|
status_trace("dev_disconnect: %s%s", dev_disconnect_line,
|
|
dev_disconnect_nocommit ? "-nocommit" : "");
|
|
if (dev_disconnect_nocommit)
|
|
dev_suppress_commit = true;
|
|
return dev_disconnect_line[0];
|
|
}
|
|
|
|
void dev_sabotage_fd(int fd)
|
|
{
|
|
int fds[2];
|
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0)
|
|
err(1, "dev_sabotage_fd: creating socketpair");
|
|
|
|
/* Close one. */
|
|
close(fds[0]);
|
|
/* Move other over to the fd we want to sabotage. */
|
|
dup2(fds[1], fd);
|
|
close(fds[1]);
|
|
}
|
|
|
|
/* Replace fd with blackhole until dev_disconnect file is truncated. */
|
|
void dev_blackhole_fd(int fd)
|
|
{
|
|
int fds[2];
|
|
int i;
|
|
struct stat st;
|
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0)
|
|
err(1, "dev_blackhole_fd: creating socketpair");
|
|
|
|
switch (fork()) {
|
|
case -1:
|
|
err(1, "dev_blackhole_fd: forking");
|
|
case 0:
|
|
/* Close everything but the dev_disconnect_fd, the socket
|
|
* which is pretending to be the peer, and stderr. */
|
|
for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)
|
|
if (i != fds[0]
|
|
&& i != dev_disconnect_fd
|
|
&& i != STDERR_FILENO)
|
|
close(i);
|
|
|
|
/* Close once dev_disconnect file is truncated. */
|
|
for (;;) {
|
|
if (fstat(dev_disconnect_fd, &st) != 0)
|
|
err(1, "fstat of dev_disconnect_fd failed");
|
|
if (st.st_size == 0)
|
|
_exit(0);
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
close(fds[0]);
|
|
dup2(fds[1], fd);
|
|
close(fds[1]);
|
|
}
|
|
#endif
|