Created
September 1, 2019 18:44
-
-
Save rianhunter/a0bd4c9e8ab550ecadbe2464995726a8 to your computer and use it in GitHub Desktop.
Shows proper usage of sem_init()
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 <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <semaphore.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <sys/mman.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
int test_semaphore(sem_t *sem) { | |
pid_t pid; | |
pid = fork(); | |
if (pid < 0) { | |
fprintf(stderr, "failed to fork: %s\n", strerror(errno)); | |
return -1; | |
} | |
if (pid > 0) { | |
int status; | |
/* after posting, child should exit successfully */ | |
sem_post(sem); | |
printf("Waiting for child to react to sem_post()...\n"); | |
waitpid(pid, &status, 0); | |
if (!WIFEXITED(status) || WEXITSTATUS(status) > 1) { | |
return -1; | |
} | |
return !WEXITSTATUS(status); | |
} else { | |
int ret; | |
struct timespec to; | |
ret = clock_gettime(CLOCK_REALTIME, &to); | |
if (ret < 0) { | |
fprintf(stderr, "failed to clock_gettime(): %s\n", strerror(errno)); | |
return 255; | |
} | |
/* wait for sem_post() for 5 seconds */ | |
to.tv_sec += 5; | |
ret = sem_timedwait(sem, &to); | |
if (ret < 0 && errno != ETIMEDOUT) { | |
fprintf(stderr, "failed to timedwait: %s\n", strerror(errno)); | |
return 255; | |
} | |
exit(!ret ? EXIT_SUCCESS : EXIT_FAILURE); | |
} | |
/* notreached */ | |
} | |
int main() { | |
int ret; | |
sem_t stack_allocated, *mmap_shared; | |
sem_init(&stack_allocated, 1, 0); | |
ret = test_semaphore(&stack_allocated); | |
if (ret < 0) { | |
return EXIT_FAILURE; | |
} | |
if (!ret) { | |
printf("Stack-allocated semaphore across fork() is broken\n"); | |
} else { | |
printf("Stack-allocated semaphore across fork() works\n"); | |
} | |
printf("\n"); | |
mmap_shared = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); | |
if (mmap_shared == MAP_FAILED) { | |
return EXIT_FAILURE; | |
} | |
sem_init(mmap_shared, 1, 0); | |
ret = test_semaphore(mmap_shared); | |
if (ret < 0) { | |
return EXIT_FAILURE; | |
} | |
if (!ret) { | |
printf("Mapped semaphore across fork() is broken\n"); | |
} else { | |
printf("Mapped semaphore across fork() works\n"); | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment