Skip to content

Conversation

@EdmondDantes
Copy link

Problem

On Windows, the shmop extension functions (shmop_open, shmop_delete, etc.) were not setting errno properly when operations failed. This resulted in unhelpful error messages like "No error" instead of meaningful diagnostics.

Additionally, shmctl(IPC_RMID) did not properly close the Windows file mapping handle, causing shared memory segments to persist even after deletion.

Solution

1. Windows-to-POSIX errno Mapping (tsrm_win32.c)

Introduced tsrm_set_errno_from_win32_error() function that converts Windows error codes to POSIX errno values:

Windows Error POSIX errno
ERROR_ACCESS_DENIED EACCES
ERROR_NOT_ENOUGH_MEMORY, ERROR_OUTOFMEMORY ENOMEM
ERROR_INVALID_PARAMETER, ERROR_INVALID_HANDLE EINVAL
ERROR_ALREADY_EXISTS EEXIST
ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND ENOENT

2. errno Set in All Error Paths

shmget():

  • EINVAL — invalid size (0 or overflow)
  • EEXIST — segment exists when IPC_EXCL flag is set
  • ENOMEM — failed to allocate internal structure
  • Windows error mapping for CreateFileMapping/OpenFileMapping failures

shmdt():

  • EINVAL — invalid segment address
  • Windows error mapping for UnmapViewOfFile failures

shmctl():

  • EINVAL — invalid key or unknown command

3. Proper Handle Cleanup in IPC_RMID

When shmctl(IPC_RMID) is called and no processes are attached, the Windows file mapping handle is now properly closed with CloseHandle(). This allows Windows to destroy the named mapping object, matching POSIX semantics where IPC_RMID marks the segment for deletion.

Files Changed

  • TSRM/tsrm_win32.c — Core implementation

Tests Added

  • ext/shmop/tests/shmop_errno_codes_win32.phpt
  • ext/shmop/tests/shmop_errno_mapping_win32.phpt
  • ext/shmop/tests/shmop_errno_tests.phpt
  • ext/shmop/tests/shmop_error_conditions_win32.phpt

Result

Error messages are now meaningful:

  • Before: Unable to attach or create shared memory segment "No error"
  • After: Unable to attach or create shared memory segment "File exists"

Add proper errno setting for all error paths in shmget() on Windows.
Introduces tsrm_set_errno_from_win32_error() to map Windows error codes
to POSIX errno values (EACCES, ENOMEM, EINVAL, EEXIST, ENOENT).

This ensures that shmop_open() can provide meaningful error messages
to users instead of "No error" when operations fail.

Tests added to verify errno mapping for different error conditions.
Set errno for error conditions in shmdt() and shmctl():
- EINVAL for invalid segment address/key
- Windows error mapping for UnmapViewOfFile failures
- EINVAL for unknown shmctl commands

This completes errno handling for all shmop system calls on Windows.
Add proper handle cleanup when marking shared memory segment for deletion.
Previously, shmctl(IPC_RMID) only marked the segment by setting key to -1
but did not close the Windows file mapping handle, causing the segment to
persist in the system.

This led to errors when trying to reopen segments with the same key:
- Segment remained accessible via OpenFileMapping()
- But had key = -1, failing validation checks
- Resulted in "Invalid argument" errors

Now properly closes the handle, allowing Windows to destroy the named
mapping object when no processes are attached, matching POSIX semantics
where IPC_RMID marks segment for deletion.

Fixes issue where shmop_open() with 'c' flag fails after shmop_delete().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant