Поскольку вы используете System V IPC, а не POSIX IPC, проверьте значение shm_nattch
в структуре данных, связанной с идентификатором сегмента разделяемой памяти. Вы можете получить это значение, вызвав shmctl
с флагом IPC_STAT
. Вызов shmdt
уменьшит это значение на единицу, и последний процесс, который вызовет эту функцию, установит значение shm_nattach
в 0
. После обнуления значения вы можете безопасно позвонить на shmctl
, чтобы удалить сегмент памяти.
Таким образом, в коде вашего клиента и сервера, если сервер не гарантированно переживет клиента, вы должны проверить значение shm_nattch
с отдельным вызовом shmctl
после вызова shmdt
, чтобы узнать, является ли число процессы, обращающиеся к сегменту разделяемой памяти, сведены к нулю. Вы также должны убедиться в том, что проверили на ошибки результаты этого вызова IPC_STAT
, чтобы избежать состояния гонки, когда два отдельных процесса вызывают shmdt
, уменьшая значение shm_nattch
до нуля, но процесс, который был на самом деле последний вызов shmdt
приостанавливается операционной системой, а другой процесс видит значение shm_nattch
равным нулю и удаляет сегмент памяти. Поскольку для проверки и удаления сегмента совместно используемой памяти требуются вызовы shm_ctl
, и этот вызов не будет выполнен, если идентификатор сегмента совместно используемой памяти недействителен, теоретически не следует сталкиваться с какими-либо условиями гонки, если вы только совершает вызовы shm_ctl
или shmdt
после того, как один процесс удалил сегмент совместно используемой памяти. Однако вам следует избегать доступа к указателю на сегмент общей памяти после его удаления. Проверка неудавшихся звонков на shm_ctl
поможет вам избежать подобных ситуаций. Другими словами, если вызов не удался, вы больше не сможете безопасно обращаться к указателю.
Если, с другой стороны, ваш сервер гарантированно переживет любого из клиентов, то сервер может безопасно выполнить вызов для удаления сегмента общей памяти, поскольку он будет последним процессом, использующим его ... все другим клиентам не нужно удалять сегмент памяти, а просто отсоединять от него.