Что-то у меня мозоли от попыток задействовать IPC-семафоры:
- shared posix mutexes - нету (из всех «бздей» есть только у FreeBSD и то с выкрутасами);
- POSIX.1 семафоры отключены еще в v5.5 (Revert to return EPERM for sem_init(3) pshared until it works properly). Причем в NetBSD и DragonFly эти семафоры больные (вплоть до сore dump).
- SysV семафоры похоже глючат.
На самом деле сложно понять что именно глючит (может у меня руки кривые) без допиливания теста. Но тот-же код работает на Linux, FreeBSD, NetBSD, DragonFly, Darwin и Solaris (OpenIndiana).
На этом фоне были замечены глюки ядра OpenBSD. Например, после заполнения /tmp (tmpfs), после последующей очистки и до перезагрузки semget() стабильно выдавала «no space left on device», а ipcs выдавала встроенный help вместо обработки опций.
На OpenBSD еще есть futex-ы (aka benaphores) портированные из Linux. Соответственно, можно попробовать их в IPC-блокировках. Но я уже сомневаюсь - стоит ли тратить время на это «унылое говно»? (уж извините).
Вскрытие стюардессы показало, что причина уже не в SysV-семафорах (они работают), а в Buffer/Page Cache.
Технически происходит следующее:
- файл mmap-ится в память несколькими процессами в режиме read-only.
- один из процессов обновляет фрагмент файла, например через pwrite() или writev() и затем инвалидирует mmap и/или кэш CPU.
- все процессы видят изменения в своих mmap-регионах.
Упомянутая инвалидация mmap не требуется во всех актуальных операционках. Только MIPS требует инвалидировать кэш CPU. Но на всякий случай попробовал и с msync().
Так вот, проблема в том, что на OpenBSD третий пункт выполняется не всегда. Даже если явно пнуть ядро посредством msync(MS_INVALIDATE).
При этом, если mmap-ить файл в read-write режиме и менять данные не через запись файл, а непосредственно в памяти то всё работает.
Короче, диагноз ясен. Напишу в bugs@openbsd.org, может-быть поправят.
Добавлено 2019-11-14: На сабмит в bugs@openbsd.org был получен ответ «это не баг, а фича». Лично для меня открытие, что оказывается в OpenBSD «by design» либо mmap, либо write(fd).