Hi all,
I have a build tool that I’ve written in Ruby that uses this construct
to
enter a directory, perform some long-running (several seconds) tasks
then
exit back to the original working directory:
FileUtils.cd(dir) do
expensive operations
end
Now I’m trying to write another tool that uses this build library to run
several builds at once in different Threads. Problem is, the
FileUtils.cd
commands overlap and conflict with each other, causing the builds to
fail. I
have a lot of code already out in production that relies on this
directory
being set correctly (users can write hooks into the build system, and
these
hooks assume a certain working directory), so I can’t remove the cd()
call.
My question is, is there a way of setting the working directory on a
per-thread basis, or is it a global property of the Ruby process that
cannot
be made thread-safe?
Cheers,
James
The current working process is a global property of the underlaying
system process.
A system Process has one currency working directory, not two, or more.
You can do your directory / filename calculations, using the absolute
directory path, without any race conditions.
–
Markus
2009/9/20 Markus S. [email protected]
The current working process is a global property of the underlaying system
process.
A system Process has one currency working directory, not two, or more.
You can do your directory / filename calculations, using the absolute
directory path, without any race conditions.
Yes, I realise now I should have forced users to use absolute paths, but
as
it stands there’s code out in the wild with stuff like:
hook :after_build do |build|
FileUtils.cp ‘README’, File.join(build.build_dir, ‘README’)
end
So the working directory needs to be set so that ‘README’ can be found
correctly. Internally the tool uses absolute paths, so e.g.
build.build_dir
is an absolute path, but code written by users is
likely
to use relative paths.
Forcing the users to use absolute paths may just hides the problem.
Maybe you should expand the users “relative” paths before using them.
Or monkeypatch FileUtils, and maybe dozens ruby core classes to support
a “thread-safe” cwd.
2009/9/20 Markus S. [email protected]:
Forcing the users to use absolute paths may just hides the problem. Maybe
you should expand the users “relative” paths before using them.
Or monkeypatch FileUtils, and maybe dozens ruby core classes to support a
“thread-safe” cwd.
That would be an option but IMHO it would be tedious and error prone.
You can easily miss a class and introduce unwanted effects.
As far as I can see the only way to make cwd thread safe would be to
use the block form and synchronize access, i.e. one thread changes
cwd, does its work and returns cwd to the old status. For obvious
reasons this is not really a good idea. IMHO the only reasonable way
to go is to
a) use cwd only in single threaded programs or with explicit
synchronization guards
b) do not change cwd and use absolute path names, even if that means
converting user input / method arguments
Kind regards
robert