Fix a multiple-sockets-in-one-process issue.
"pid" is not "process id" in netlink, but rather, "port id". If you bind to a sockaddr == 0 then Linux automatically assigns your socket a port id - which happens to be the same as the process ID for the first one concurrently open. For the second and subsequent concurrently-open sockets, binding 0 (as most users of this library will do) gets you back a random high-numbered port id. This change preserves the existing use case (one port open in the process, binding to 0) while fixing multiple-ports-open-in-the-same-process, socket-is- passed-in-and-pid-is-not-specified, and specific-pid-is-requested-but-could- not-bind-to-it. We're probably still not thread-safe - the seq handling looks dodgy - but at least now we can use multiple sockets in separate threads and have them all work. Using the same socket from multiple threads is a slightly niche use case, and it's tempting to say "don't do this" instead...
This commit is contained in:
@@ -58,14 +58,16 @@ module Netlink
|
||||
# :timeout => N (seconds, default to DEFAULT_TIMEOUT. Pass nil for no timeout)
|
||||
# :junk_handler => lambda { ... } for unexpected packets
|
||||
def initialize(opt)
|
||||
@socket ||= opt[:socket] || ::Socket.new(
|
||||
@socket = opt[:socket] || ::Socket.new(
|
||||
Socket::AF_NETLINK,
|
||||
Socket::SOCK_DGRAM,
|
||||
opt[:protocol] || (raise "Missing :protocol")
|
||||
)
|
||||
@socket.bind(NLSocket.sockaddr(opt)) unless opt[:socket]
|
||||
@seq = opt[:seq] || Time.now.to_i
|
||||
@pid = opt[:pid] || $$
|
||||
|
||||
@pid = @socket.getsockname.unpack(SOCKADDR_PACK)[2]
|
||||
|
||||
@timeout = opt.has_key?(:timeout) ? opt[:timeout] : DEFAULT_TIMEOUT
|
||||
if opt.has_key?(:junk_handler)
|
||||
@junk_handler = opt[:junk_handler]
|
||||
@@ -75,7 +77,7 @@ module Netlink
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Close the Netlink socket
|
||||
def close
|
||||
@socket.close
|
||||
@@ -85,7 +87,7 @@ module Netlink
|
||||
def next_seq
|
||||
@seq = (@seq + 1) & 0xffffffff
|
||||
end
|
||||
|
||||
|
||||
# Add a header and send a single message over the socket.
|
||||
# type:: the message type code
|
||||
# msg:: the message to send (without header)
|
||||
@@ -203,7 +205,7 @@ module Netlink
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Receive one datagram from kernel. Validates the sender, and returns
|
||||
# the raw binary message. Raises an exception on timeout or if the
|
||||
# kernel closes the socket.
|
||||
|
Reference in New Issue
Block a user