From 15dea14dd4e1af97aef928430c3c8ef8c5d74451 Mon Sep 17 00:00:00 2001 From: Brian Corrigan Date: Tue, 5 Jun 2012 11:46:34 -0400 Subject: resolve symlinks to Unix domain sockets Raindrops currently fails when provided a symlink to a socket. As this is a common practice for many deployment tools (Vlad, etc.) this patch adds support for finding the realpath prior to looking the socket up in /proc/net/unix [ew: commit message subject] [ew: fixed test to pass under 1.9.3 and 1.8.7: * Tempfile#unlink is unsafe to call if we want to reuse the path, use File.unlink(tmp.path) instead * The return value of File.symlink is zero (or it raises), so it's unusable. * File.symlink will not call #to_path under 1.8.7, so it's necessary to pass pathnames to it, not Tempfile objects. ] Signed-off-by: Eric Wong --- lib/raindrops/linux.rb | 3 +++ test/test_linux.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/raindrops/linux.rb b/lib/raindrops/linux.rb index fe2af09..a198253 100644 --- a/lib/raindrops/linux.rb +++ b/lib/raindrops/linux.rb @@ -8,6 +8,8 @@ # Instead of snapshotting, Raindrops::Aggregate::LastDataRecv may be used # to aggregate statistics from +all+ accepted sockets as they arrive # based on the +last_data_recv+ field in Raindrops::TCP_Info +require 'pathname' + module Raindrops::Linux # The standard proc path for active UNIX domain sockets, feel free to call @@ -41,6 +43,7 @@ module Raindrops::Linux else paths = paths.map do |path| path = path.dup + path = Pathname.new(path).realpath.to_s path.force_encoding(Encoding::BINARY) if defined?(Encoding) rv[path] Regexp.escape(path) diff --git a/test/test_linux.rb b/test/test_linux.rb index 65f25e0..81463c9 100644 --- a/test/test_linux.rb +++ b/test/test_linux.rb @@ -67,6 +67,32 @@ class TestLinux < Test::Unit::TestCase assert_equal 1, stats[tmp.path].queued end + def test_unix_resolves_symlinks + tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :) + File.unlink(tmp.path) + us = UNIXServer.new(tmp.path) + + # Create a symlink + destination = Tempfile.new("somethingelse") + destination.unlink # We need an available name, not an actual file + link = File.symlink(tmp, destination) + + @to_close << UNIXSocket.new(tmp.path) + stats = unix_listener_stats + assert_equal 0, stats[link.path].active + assert_equal 1, stats[link.path].queued + + @to_close << UNIXSocket.new(tmp.path) + stats = unix_listener_stats + assert_equal 0, stats[link.path].active + assert_equal 2, stats[link.path].queued + + @to_close << us.accept + stats = unix_listener_stats + assert_equal 1, stats[link.path].active + assert_equal 1, stats[link.path].queued + end + def test_tcp s = TCPServer.new(TEST_ADDR, 0) port = s.addr[1] -- cgit v1.2.3-24-ge0c7