Class: IO::Endpoint::UNIXEndpoint

Inherits:
AddressEndpoint show all
Defined in:
lib/io/endpoint/unix_endpoint.rb

Overview

This class doesn't exert ownership over the specified unix socket and ensures exclusive access by using flock where possible.

Instance Attribute Summary collapse

Attributes inherited from AddressEndpoint

#The network address for this endpoint., #address

Attributes inherited from Generic

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AddressEndpoint

#connect

Methods inherited from Generic

#accept, #bound, #connect, #connected, #each, #hostname, #linger, #local_address, parse, #reuse_address?, #reuse_port?, #timeout, #with, #wrapper

Constructor Details

#initialize(path, type = Socket::SOCK_STREAM, **options) ⇒ UNIXEndpoint

Initialize a new UNIX domain socket endpoint.



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/io/endpoint/unix_endpoint.rb', line 31

def initialize(path, type = Socket::SOCK_STREAM, **options)
	@path = path
	
	begin
		address = Address.unix(path, type)
	rescue ArgumentError
		path = self.class.short_path_for(path)
		address = Address.unix(path, type)
	end
	
	super(address, **options)
end

Instance Attribute Details

#The path to the UNIX socket.(pathtotheUNIXsocket.) ⇒ Object (readonly)



63
64
65
# File 'lib/io/endpoint/unix_endpoint.rb', line 63

def path
	@path
end

Class Method Details

.short_path_for(path) ⇒ Object

Compute a stable temporary UNIX socket path for an overlong path.



19
20
21
22
23
24
25
# File 'lib/io/endpoint/unix_endpoint.rb', line 19

def self.short_path_for(path)
	# We need to ensure the path is absolute and canonical, otherwise the SHA1 hash will not be consistent:
	path = File.expand_path(path)
	
	# We then use the SHA1 hash of the path to create a short, stable path:
	File.join(Dir.tmpdir, Digest::SHA1.hexdigest(path) + ".ipc")
end

Instance Method Details

#bindObject

Bind the UNIX socket, handling stale socket files.



93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/io/endpoint/unix_endpoint.rb', line 93

def bind(...)
	result = super
	create_symlink_if_required!
	return result
rescue Errno::EADDRINUSE
	# If you encounter EADDRINUSE from `bind()`, you can check if the socket is actually accepting connections by attempting to `connect()` to it. If the socket is still bound by an active process, the connection will succeed. Otherwise, it should be safe to `unlink()` the path and try again.
	if !bound?
		unlink_stale_paths!
		retry
	else
		raise
	end
end

#bound?Boolean

Check if the socket is currently bound and accepting connections.

Returns:

  • (Boolean)


78
79
80
81
82
83
84
85
86
# File 'lib/io/endpoint/unix_endpoint.rb', line 78

def bound?
	self.connect do
		return true
	end
rescue Errno::ECONNREFUSED
	return false
rescue Errno::ENOENT
	return false
end

#inspectObject

Get a detailed string representation of the UNIX endpoint.



52
53
54
55
56
57
58
59
60
# File 'lib/io/endpoint/unix_endpoint.rb', line 52

def inspect
	target_path = @address.unix_path
	
	if @path == target_path
		"\#<#{self.class} path=#{@path.inspect}>"
	else
		"\#<#{self.class} path=#{@path.inspect} target=#{target_path.inspect}>"
	end
end

#pathObject



63
64
65
# File 'lib/io/endpoint/unix_endpoint.rb', line 63

def path
	@path
end

#symlink?Boolean

Check if a symlink is used for this endpoint.

A symlink is created when the original path exceeds the system's maximum UNIX socket path length and a shorter temporary path is used for the actual socket.

Returns:

  • (Boolean)


72
73
74
# File 'lib/io/endpoint/unix_endpoint.rb', line 72

def symlink?
	File.symlink?(@path)
end

#to_sObject

Get a string representation of the UNIX endpoint.



46
47
48
# File 'lib/io/endpoint/unix_endpoint.rb', line 46

def to_s
	"unix:#{@path}"
end