Skip to content

Commit bbb751b

Browse files
Better shm name.
1 parent df78171 commit bbb751b

1 file changed

Lines changed: 17 additions & 12 deletions

File tree

lib/io/memory/posix.rb

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ def self.supported?
2020
@supported
2121
end
2222

23-
# POSIX shared memory constants
24-
O_CREAT = 0x0200
25-
O_EXCL = 0x0800
26-
O_RDWR = 0x0002
23+
# Use Ruby's File constants instead of hardcoded values for cross-platform compatibility
24+
O_CREAT = IO::CREAT
25+
O_EXCL = IO::EXCL
26+
O_RDWR = IO::RDWR
2727

2828
# Load system functions
2929
LIBC = Fiddle.dlopen(nil)
@@ -84,13 +84,11 @@ def self.create_handle(size)
8484
# Generate a unique name using multiple entropy sources to avoid collisions
8585
# in high-concurrency situations
8686
max_attempts = 8
87+
last_error = nil
8788

8889
max_attempts.times do
89-
# Combine multiple entropy sources for uniqueness:
90-
# - Process PID
91-
# - Thread object ID (unique per thread)
92-
# - Microsecond timestamp
93-
shm_name = "/#{Process.pid}_#{Fiber.current.object_id}_#{Time.now.usec}"
90+
# The most portable maximum length for a POSIX shared memory name is 14 characters:
91+
shm_name = "/#{SecureRandom.hex(7)}"
9492

9593
# Create shared memory object with O_EXCL to ensure uniqueness
9694
shm_fd = SHM_OPEN.call(shm_name, O_CREAT | O_EXCL | O_RDWR, 0600)
@@ -100,20 +98,27 @@ def self.create_handle(size)
10098
if FTRUNCATE.call(shm_fd, size) == 0
10199
# Create IO object from file descriptor
102100
io = ::IO.for_fd(shm_fd, autoclose: true)
103-
101+
104102
# Return Handle that manages both IO and cleanup
105103
return Handle.new(io, shm_name, size)
106104
else
107105
# ftruncate failed, clean up
108106
SHM_UNLINK.call(shm_name)
109107
raise IO::Memory::MemoryError, "Failed to set shared memory size to #{size}!"
110108
end
109+
else
110+
# Store the error for potential debugging
111+
last_error = Fiddle.last_error
111112
end
112113
# If we get here, shm_open failed (likely name collision), try again with new name
113114
end
114115

115-
# If we've exhausted all attempts
116-
raise IO::Memory::MemoryError, "Failed to create shared memory object after #{max_attempts} attempts!"
116+
# If we've exhausted all attempts:
117+
if last_error
118+
cause = SystemCallError.new(last_error)
119+
end
120+
121+
raise IO::Memory::MemoryError, "Failed to create shared memory object after #{max_attempts} attempts!", cause: cause
117122
end
118123

119124
@supported = true

0 commit comments

Comments
 (0)