It may be that this is best classified as a bug in Ruby, but I've had it affect needle-based code fairly frequently,
so I wonder if there is a workaround that can be put in needle for now.
This has been reproduced primarily on Ruby 1.8.6p111, needle 1.3.0. The OS platform is Mac OS X 10.4.10 (Intel), though
I don't believe it to be relevant.
The core issue seems to be that Kernel#require is not properly re-entrant. If two threads simultaneously require the
same file (that has not yet been loaded), the first will parse through the file, while the second may return false
immediately *before* the first has completed. As a result, the second thread may then attempt to access constants defined
in the required file that the first thread has not yet added to the ruby runtime's namespace.
In needle, this can cause errors in Container#require, which first requires a file, and then may attempt to const_get
a constant defined in that file. In the above scenario in which two threads call the same Container#require simultaneously,
the second thread may attempt to reference the constant before the first thread has defined it, resulting in a NameError
being thrown out of the second thread.
My use case that reproduces this frequently involves a program based on net-ssh (which uses needle). I may attempt,
for example, to use net-ssh to connect to two servers in two different threads in parallel, one thread managing each
server. The two threads both register net-ssh's services simultaneously, which sometimes results in the above scenario.
|