concurrent-read-write.c
text/x-csrc
Filename: concurrent-read-write.c
Type: text/x-csrc
Part: 0
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define LOOPS 100000000
#define BYTES 8192
static void
writer(int fd)
{
char buffer1[BYTES];
char buffer2[BYTES];
memset(buffer1, '1', sizeof(buffer1));
memset(buffer2, '2', sizeof(buffer2));
for (int i = 0; i < LOOPS; ++i) {
if (pwrite(fd, i % 2 == 0 ? buffer1 : buffer2, BYTES, 0) != BYTES) {
perror("pwrite failed");
break;
}
if (ftruncate(fd, 0) != 0)
{
perror("ftruncate failed");
break;
}
}
close(fd);
}
static void
reader(int readerno, int fd)
{
char buffer[BYTES];
char buffer1[BYTES];
char buffer2[BYTES];
memset(buffer1, '1', sizeof(buffer1));
memset(buffer2, '2', sizeof(buffer2));
for (int i = 0; i < LOOPS; ++i) {
ssize_t r;
r = pread(fd, buffer, BYTES, 0);
if (r == 0 || r == 4096)
continue;
else if (r != BYTES) {
fprintf(stderr, "[%d] perror: returned %zd: %m\n",
readerno, r);
}
if (memcmp(buffer, buffer1, BYTES) != 0 &&
memcmp(buffer, buffer2, BYTES) != 0) {
char b0 = buffer[0];
if (b0 == 0)
{
printf("found 0\n");
}
for (int i = 1; i < BYTES; ++i)
{
if (b0 != buffer[i])
{
fprintf(stderr, "[%d] difference at byte %d, byte before: %02x, byte: %02x\n",
readerno, i, buffer[i - 1], buffer[i]);
break;
}
}
}
}
close(fd);
return;
}
int main(int argc, char *argv[])
{
#define NCHILDREN 80
int childpids[NCHILDREN];
int fd;
fd = open("test-file", O_RDWR | O_CREAT, 0644);
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
for (int i = 0; i < NCHILDREN; i++)
{
int pid = fork();
if (pid < 0) {
fprintf(stderr, "fork failed\n");
return EXIT_FAILURE;
}
else if (pid == 0)
{
reader(i, fd);
fprintf(stderr, "[%d] reader done\n", i);
exit(0);
}
else
{
childpids[i] = pid;
}
}
int status;
writer(fd);
fprintf(stderr, "writer done, killing readers\n");
for (int i = 0; i < NCHILDREN; i++)
kill(childpids[i], SIGTERM);
for (int i = 0; i < NCHILDREN; i++)
waitpid(childpids[i], &status, 0);
return status;
}