Hi,

I've improved yesterday's patch.  This patch will be more effective.
I've tested Ruby bindings with my subversion/svnserve/main.c inserted
sleep() before calling apr_socket_bind().

Thanks,

-nori
Index: subversion/bindings/swig/ruby/test/util.rb
===================================================================
--- subversion/bindings/swig/ruby/test/util.rb  (revision 20818)
+++ subversion/bindings/swig/ruby/test/util.rb  (working copy)
@@ -1,4 +1,5 @@
 require "fileutils"
+require "socket"
 
 require "svn/client"
 require "svn/repos"
@@ -106,8 +107,8 @@
              "-d", "--foreground")
       }
       pid, status = Process.waitpid2(@svnserve_pid, Process::WNOHANG)
-      if status and status.exited?
-        STDERR.puts "port #{port} couldn't be used for svnserve"
+      if (status and status.exited?) or (not svnserve_available_at?(port))
+        STDERR.puts "svnserve couldn't get available at port #{port}"
       else
         @svnserve_port = port
         @repos_svnserve_uri =
@@ -129,6 +130,7 @@
         Process.waitpid(@svnserve_pid)
       rescue Errno::ECHILD
       end
+      @svnserve_pid = nil
     end
   end
 
@@ -222,4 +224,21 @@
     auth_baton[Svn::Core::AUTH_PARAM_CONFIG_DIR] = @config_path
     auth_baton[Svn::Core::AUTH_PARAM_DEFAULT_USERNAME] = @author
   end
+
+  # Check whether svnserve gets available at port +port+ to avoid the race
+  # condition between starting up a svnserve process and trying to connect
+  # to it (Bug#378837 in Debian's BTS).  Returns +true+ when svnserve gets
+  # available.
+  def svnserve_available_at?(port)
+    begin
+      50.times do |n|
+        TCPServer.new(port).close
+        sleep 0.1 + rand(0.2)
+      end
+      teardown_svnserve
+      false
+    rescue Errno::EADDRINUSE
+      true
+    end
+  end
 end

Reply via email to