Created
June 29, 2024 03:42
-
-
Save sjolsen/4df00bc861d9f6d960f6cb426ec58247 to your computer and use it in GitHub Desktop.
demonstrating shared file description state across fork
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <errno.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/wait.h> | |
#include <unistd.h> | |
int write_all(int fd, const void *buf, size_t count) { | |
const char *cbuf = (const char *)buf; | |
while (count > 0) { | |
ssize_t rv = write(fd, cbuf, count); | |
if (rv == (ssize_t)-1) { | |
switch (errno) { | |
case EAGAIN: | |
#if EAGAIN != EWOULDBLOCK | |
case EWOULDBLOCK: | |
#endif | |
case EINTR: | |
continue; | |
default: | |
return errno; | |
} | |
} | |
size_t written = (size_t)rv; | |
cbuf += written; | |
count -= written; | |
} | |
return 0; | |
} | |
int read_all(int fd, void *buf, size_t count) { | |
char *cbuf = (char *)buf; | |
while (count > 0) { | |
ssize_t rv = read(fd, cbuf, count); | |
if (rv == (ssize_t)-1) { | |
switch (errno) { | |
case EAGAIN: | |
#if EAGAIN != EWOULDBLOCK | |
case EWOULDBLOCK: | |
#endif | |
case EINTR: | |
continue; | |
default: | |
return errno; | |
} | |
} | |
size_t nread = (size_t)rv; | |
cbuf += nread; | |
count -= nread; | |
} | |
return 0; | |
} | |
int main(int argc, char **argv) { | |
if (argc != 2) { | |
fprintf(stderr, "Usage: %s file\n", argv[0] ? argv[0] : "fork_fd"); | |
return EXIT_FAILURE; | |
} | |
const char *filename = argv[1]; | |
int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0777); | |
if (fd < 0) { | |
fprintf(stderr, "open: %s: %s\n", strerror(errno), filename); | |
return EXIT_FAILURE; | |
} | |
const char *data = "Hello, world!\n"; | |
int status = write_all(fd, data, strlen(data)); | |
if (status != 0) { | |
fprintf(stderr, "write: %s: %s\n", strerror(status), filename); | |
return EXIT_FAILURE; | |
} | |
off_t offset = lseek(fd, 0, SEEK_SET); | |
if (offset == (off_t)-1) { | |
fprintf(stderr, "lseek: %s: %s\n", strerror(errno), filename); | |
return EXIT_FAILURE; | |
} | |
pid_t pid = fork(); | |
if (pid == (pid_t)-1) { | |
fprintf(stderr, "fork: %s\n", strerror(errno)); | |
return EXIT_FAILURE; | |
} | |
if (pid == 0) { | |
// Child | |
char rbuf[8]; | |
status = read_all(fd, rbuf, 7); | |
if (status != 0) { | |
fprintf(stderr, "read: %s: %s\n", strerror(status), filename); | |
return EXIT_FAILURE; | |
} | |
rbuf[7] = '\0'; | |
printf("Child process: read '%s'\n", rbuf); | |
} else { | |
// Parent | |
int wstatus; | |
pid_t wait_rv = waitpid(pid, &wstatus, 0); | |
if (wait_rv == (pid_t)-1) { | |
fprintf(stderr, "wait: %s\n", strerror(errno)); | |
return EXIT_FAILURE; | |
} | |
if (!WIFEXITED(wstatus)) { | |
fprintf(stderr, "wait: child process exited abnormally\n"); | |
return EXIT_FAILURE; | |
} | |
if (WEXITSTATUS(wstatus) != 0) { | |
return WEXITSTATUS(wstatus); | |
} | |
char rbuf[8]; | |
status = read_all(fd, rbuf, 7); | |
if (status != 0) { | |
fprintf(stderr, "read: %s: %s\n", strerror(status), filename); | |
return EXIT_FAILURE; | |
} | |
rbuf[7] = '\0'; | |
printf("Parent process: read '%s'\n", rbuf); | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment