#include <sys/param.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
static void growshrink(const char *);
static void writer(const char *, int);
static int npages = 2;
int
test_deadlock(struct context *ctx)
{
int killpip[2];
int status;
pid_t pid;
if (pipe2(killpip, O_NONBLOCK) == -1)
err(1, "pipe2");
pid = fork();
if (pid == -1)
err(1, "fork");
if (pid == 0) {
close(killpip[1]);
writer(ctx->c_path, killpip[0]);
return 0;
}
close(killpip[0]);
fprintf(stderr, "parent = %d, child = %d\n", getpid(), pid);
for (;;) {
if (ctx_abort(ctx))
break;
growshrink(ctx->c_path);
}
write(killpip[1], "X", 1);
close(killpip[1]);
if (waitpid(pid, &status, 0) == -1)
err(1, "waitpid");
if (WIFSIGNALED(status))
return 128 + WTERMSIG(status);
if (WIFEXITED(status))
return WEXITSTATUS(status);
return 0;
}
static void
growshrink(const char *path)
{
char *p;
int fd;
fd = open(path, O_RDWR | O_TRUNC);
if (fd == -1)
err(1, "open: %s", path);
if (ftruncate(fd, npages * PAGE_SIZE) == -1)
err(1, "ftruncate");
p = mmap(NULL, npages * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0);
if (p == MAP_FAILED)
err(1, "mmap");
memset(&p[(npages - 1) * PAGE_SIZE], 'x', PAGE_SIZE);
if (munmap(p, npages * PAGE_SIZE) == -1)
err(1, "munmap");
close(fd);
}
static void
writer(const char *path, int killfd)
{
char *p;
int fd;
char c;
fd = open(path, O_RDONLY);
if (fd == -1)
err(1, "open: %s", path);
p = mmap(NULL, npages * PAGE_SIZE, PROT_READ, MAP_SHARED,
fd, 0);
if (p == MAP_FAILED)
err(1, "mmap");
for (;;) {
const struct iovec *iov = (const struct iovec *)p;
if (read(killfd, &c, 1) == 1)
break;
pwritev(-1, iov, 1, 0);
}
}