Skip to content

Commit df31b57

Browse files
author
Joshua Liebowitz
committed
fork() when using Dir.chdir, otherwise, use a mutex
Signed-off-by: Joshua Liebowitz <taquitos@google.com>
1 parent ba1df97 commit df31b57

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

lib/git/base.rb

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
module Git
44

55
class Base
6+
# Adding a mutex to the class because each repo should be sharing the same mutex
7+
# in case we need to Dir.chdir and we don't have fork() support to isolate that
8+
class << self
9+
attr_accessor :chdir_semaphore
10+
end
11+
Git::Base.chdir_semaphore = Mutex.new
612

713
include Git::Base::Factory
814

@@ -92,18 +98,37 @@ def initialize(options = {})
9298
@index = options[:index] ? Git::Index.new(options[:index], false) : nil
9399
end
94100

95-
# changes current working directory for a block
96-
# to the git working directory
101+
# changes current working directory for a block to the git working directory.
102+
#
103+
# Note: If we can fork() or spawn(), Dir.chdir will happen in a new process
104+
# otherwise, we will use a mutex to prevent threading errors
105+
# See https://github.com/ruby-git/ruby-git/issues/355 for more info
97106
#
98107
# example
99108
# @git.chdir do
100109
# # write files
101110
# @git.add
102111
# @git.commit('message')
103112
# end
104-
def chdir # :yields: the Git::Path
105-
Dir.chdir(dir.path) do
106-
yield dir.path
113+
def chdir(&block) # :yields: the Git::Path
114+
chdir_block = Proc.new do
115+
Dir.chdir(dir.path) do
116+
block.call(dir.path)
117+
end
118+
end
119+
120+
if Process.respond_to?(:fork)
121+
# Forking this process so that we can be threadsafe
122+
pid = Process.fork do
123+
chdir_block.call
124+
end
125+
Process.wait(pid)
126+
else
127+
# Windows and NetBSD 4 don't support fork()
128+
# let's use a mutex to prevent race conditions with threads
129+
Git::Base.chdir_semaphore.synchronize do
130+
chdir_block.call
131+
end
107132
end
108133
end
109134

0 commit comments

Comments
 (0)