Implement unix with sem_*(3) instead of pipes (dispatch_semaphore_*() on apple where POSIX semaphores are broken-by-design)#134
Merged
Detegr merged 3 commits intoDetegr:masterfrom Sep 6, 2025
nabijaczleweli:master
Merged
Implement unix with sem_*(3) instead of pipes (dispatch_semaphore_*() on apple where POSIX semaphores are broken-by-design)#134Detegr merged 3 commits intoDetegr:masterfrom nabijaczleweli:master
Detegr merged 3 commits intoDetegr:masterfrom
nabijaczleweli:master
Conversation
Contributor
Author
|
...and with dispatch_semaphore_*()s on apple since apple refuses to ship POSIX semaphores, still comes out to net -39 :) |
Contributor
Author
|
(ftr I did originally cook up an even-thinner implementation since you don't need any sync primitives if you sigsetmask+SIGINT in the main thread/SIGSETMASK-SIGINT in the waiter/pause BUT the signal mask must be set in all threads, so it must be set before any non-default threads are spawned; would be nice, but not a viable restriction) |
Using pipes works, but is unnecessarily thick
for a one-shot application like this,
and leaves 2 largely-useless pipe fds in the process permanently
sem_post(3) is explicitly allowed to be used in signal handlers,
this is practically the target application of POSIX semaphores
readme_example/glibc before:
3735433 rt_sigaction(SIGBUS, {sa_handler=0x56412e4350e0, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_SIGINFO, sa_restorer=0x7f57bb5dd050}, NULL, 8) = 0
3735433 pipe2([3, 4], O_CLOEXEC) = 0
3735433 fcntl(4, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
3735433 rt_sigaction(SIGINT, {sa_handler=0x56412e40b410, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f57bb5dd050}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
3735433 rt_sigaction(SIGRT_1, {sa_handler=0x7f57bb627720, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f57bb5dd050}, NULL, 8) = 0
3735433 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
3735433 mmap(NULL, 2101248, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f57bb39d000
3735433 mprotect(0x7f57bb39e000, 2097152, PROT_READ|PROT_WRITE) = 0
3735433 rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
3735433 clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, child_tid=0x7f57bb59d990, parent_tid=0x7f57bb59d990, exit_signal=0, stack=0x7f57bb39d000, stack_size=0x1fff00, tls=0x7f57bb59d6c0} => {parent_tid=[3735438]}, 88) = 3735438
3735438 rseq(0x7f57bb59dfe0, 0x20, 0, 0x53053053 <unfinished ...>
3735433 rt_sigprocmask(SIG_SETMASK, [], <unfinished ...>
3735438 <... rseq resumed>) = 0
3735433 <... rt_sigprocmask resumed>NULL, 8) = 0
3735438 set_robust_list(0x7f57bb59d9a0, 24) = 0
3735433 write(1, "Waiting for Ctrl-C...\n", 22 <unfinished ...>
3735438 rt_sigprocmask(SIG_SETMASK, [], <unfinished ...>
3735433 <... write resumed>) = 22
3735438 <... rt_sigprocmask resumed>NULL, 8) = 0
3735438 mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0 <unfinished ...>
3735433 futex(0x56415f72c028, FUTEX_WAIT_BITSET_PRIVATE, 4294967295, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
3735438 <... mmap resumed>) = 0x7f57b339d000
3735438 munmap(0x7f57b339d000, 12988416) = 0
3735438 munmap(0x7f57b8000000, 54120448) = 0
3735438 mprotect(0x7f57b4000000, 135168, PROT_READ|PROT_WRITE) = 0
3735438 sched_getaffinity(3735438, 32, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]) = 8
3735438 sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
3735438 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f57bb7b5000
3735438 mprotect(0x7f57bb7b5000, 4096, PROT_NONE) = 0
3735438 sigaltstack({ss_sp=0x7f57bb7b6000, ss_flags=0, ss_size=8192}, NULL) = 0
3735438 prctl(PR_SET_NAME, "ctrl-c") = 0
3735438 read(3, <unfinished ...>
3735433 <... futex resumed>) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
3735433 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
3735433 write(4, "\0", 1) = 1
3735438 <... read resumed>"\0", 1) = 1
3735433 rt_sigreturn({mask=[]} <unfinished ...>
3735438 futex(0x56415f72c028, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
3735433 <... rt_sigreturn resumed>) = 202
3735438 <... futex resumed>) = 0
3735433 futex(0x56415f72c028, FUTEX_WAIT_BITSET_PRIVATE, 4294967295, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
3735438 read(3, <unfinished ...>
3735433 <... futex resumed>) = -1 EAGAIN (Resource temporarily unavailable)
3735433 write(1, "Got it! Exiting...\n", 19) = 19
3735433 sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
3735433 munmap(0x7f57bb7b8000, 12288) = 0
3735433 exit_group(0) = ?
3735438 <... read resumed> <unfinished ...>) = ?
3735438 +++ exited with 0 +++
3735433 +++ exited with 0 +++
After:
3864619 rt_sigaction(SIGBUS, {sa_handler=0x55d614829ed0, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_SIGINFO, sa_restorer=0x7f8750f22050}, NULL, 8) = 0
3864619 rt_sigaction(SIGINT, {sa_handler=0x55d6148008c0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f8750f22050}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
3864619 rt_sigaction(SIGRT_1, {sa_handler=0x7f8750f6c720, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f8750f22050}, NULL, 8) = 0
3864619 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
3864619 mmap(NULL, 2101248, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f8750ce2000
3864619 mprotect(0x7f8750ce3000, 2097152, PROT_READ|PROT_WRITE) = 0
3864619 rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
3864619 clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, child_tid=0x7f8750ee2990, parent_tid=0x7f8750ee2990, exit_signal=0, stack=0x7f8750ce2000, stack_size=0x1fff00, tls=0x7f8750ee26c0} => {parent_tid=[3864624]}, 88) = 3864624
3864624 rseq(0x7f8750ee2fe0, 0x20, 0, 0x53053053 <unfinished ...>
3864619 rt_sigprocmask(SIG_SETMASK, [], <unfinished ...>
3864624 <... rseq resumed>) = 0
3864619 <... rt_sigprocmask resumed>NULL, 8) = 0
3864624 set_robust_list(0x7f8750ee29a0, 24) = 0
3864619 write(1, "Waiting for Ctrl-C...\n", 22 <unfinished ...>
3864624 rt_sigprocmask(SIG_SETMASK, [], <unfinished ...>
3864619 <... write resumed>) = 22
3864624 <... rt_sigprocmask resumed>NULL, 8) = 0
3864624 mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0 <unfinished ...>
3864619 futex(0x55d64f9de028, FUTEX_WAIT_BITSET_PRIVATE, 4294967295, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
3864624 <... mmap resumed>) = 0x7f8748ce2000
3864624 munmap(0x7f8748ce2000, 53600256) = 0
3864624 munmap(0x7f8750000000, 13508608) = 0
3864624 mprotect(0x7f874c000000, 135168, PROT_READ|PROT_WRITE) = 0
3864624 sched_getaffinity(3864624, 32, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]) = 8
3864624 sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
3864624 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f87510fa000
3864624 mprotect(0x7f87510fa000, 4096, PROT_NONE) = 0
3864624 sigaltstack({ss_sp=0x7f87510fb000, ss_flags=0, ss_size=8192}, NULL) = 0
3864624 prctl(PR_SET_NAME, "ctrl-c") = 0
3864624 futex(0x55d614867988, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
3864619 <... futex resumed>) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
3864619 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
3864619 futex(0x55d614867988, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
3864624 <... futex resumed>) = 0
3864619 <... futex resumed>) = 1
3864624 futex(0x55d64f9de028, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
3864619 rt_sigreturn({mask=[]} <unfinished ...>
3864624 <... futex resumed>) = 0
3864624 futex(0x55d614867988, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
3864619 <... rt_sigreturn resumed>) = 202
3864619 futex(0x55d64f9de028, FUTEX_WAIT_BITSET_PRIVATE, 4294967295, NULL, FUTEX_BITSET_MATCH_ANY) = -1 EAGAIN (Resource temporarily unavailable)
3864619 write(1, "Got it! Exiting...\n", 19) = 19
3864619 sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
3864619 munmap(0x7f87510fd000, 12288) = 0
3864619 exit_group(0) = ?
3864624 <... futex resumed>) = ?
3864624 +++ exited with 0 +++
3864619 +++ exited with 0 +++
…ly and officially broken
Owner
|
Sorry for missing this PR. I like this, I never liked using pipes anyway. |
nabijaczleweli
added a commit
to thecoshman/http
that referenced
this pull request
Sep 29, 2025
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Using pipes works, but is unnecessarily thick for a one-shot application like this, and leaves 2 largely-useless pipe fds in the process permanently
sem_post(3) is explicitly allowed to be used in signal handlers, this is practically the target application of POSIX semaphores
readme_example/glibc before:
After: