Project

General

Profile

Actions

Bug #921

closed

autoload is not thread-safe

Added by headius (Charles Nutter) about 15 years ago. Updated about 11 years ago.

Status:
Closed
Target version:
ruby -v:
-
Backport:
[ruby-core:20797]

Description

=begin
Currently autoload is not safe to use in a multi-threaded application. To put it more bluntly, it's broken.

The current logic for autoload is as follows:

  1. A special object is inserted into the target constant table, used as a marker for autoloading
  2. When that constant is looked up, the marker is found and triggers autoloading
  3. The marker is first removed, so the constant now appears to be undefined if retrieved concurrently
  4. The associated autoload resource is required, and presumably redefines the constant in question
  5. The constant lookup, upon completion of autoload, looks up the constant again and either returns its new value or proceeds with normal constant resolution

The problem arises when two or more threads try to access the constant. Because autoload is stateful and unsynchronized, the second thread may encounter the constant table in any number of states:

  1. It may see the autoload has not yet fired, if the first thread has encountered the marker but not yet removed it. It would then proceed along the same autoload path, requiring the same file a second time.
  2. It may not find an autoload marker, and assume the constant does not exist.
  3. It may see the eventual constant the autoload was intended to define.

Of these combinations, (3) is obviously the desired behavior. (1) can only happen on native-threaded implementations that do not have a global interpreter lock, since it requires concurrency during autoload's internal logic. (2) can happen on any implementation, since while the required file is processing the original autoload constant appears to be undefined.

I have only come up with two solutions:

  • When the autoload marker is encountered, it is replaced (under lock) with an "autoload in progress" marker. All subsequent threads will then see this marker and wait for the autoloading process to complete. the mechanics of this are a little tricky, but it would guarantee concurrent autoloads would only load the target file once and would always return the intended value to concurrent readers.
  • A single autoload mutex, forcing all autoloads to happen in serial.

There is a potential for deadlock in the first solution, unfortunately, since two threads autoloading two constants with circular autoloaded constant dependencies would ultimately deadlock, each waiting for the other to complete. Because of this, a single autoload mutex for all autoloads may be the only safe solution.
=end

Actions #1

Updated by pragdave (Dave Thomas) about 15 years ago

=begin

On Dec 22, 2008, at 11:10 AM, Charles Nutter wrote:

  • When the autoload marker is encountered, it is replaced (under
    lock) with an "autoload in progress" marker. All subsequent threads
    will then see this marker and wait for the autoloading process to
    complete. the mechanics of this are a little tricky, but it would
    guarantee concurrent autoloads would only load the target file once
    and would always return the intended value to concurrent readers.
  • A single autoload mutex, forcing all autoloads to happen in serial.

There is a potential for deadlock in the first solution,
unfortunately, since two threads autoloading two constants with
circular autoloaded constant dependencies would ultimately deadlock,
each waiting for the other to complete. Because of this, a single
autoload mutex for all autoloads may be the only safe solution.

Why not use the same lock that's used by require? The two are clearly
related, and if there's a require in progress, you'd want to suspend
autoload until it has finished, and the result of the require might
affect the behavior of the autoload.

Dave

=end

Actions #2

Updated by headius (Charles Nutter) about 15 years ago

=begin
Dave Thomas wrote:

Why not use the same lock that's used by require? The two are clearly
related, and if there's a require in progress, you'd want to suspend
autoload until it has finished, and the result of the require might
affect the behavior of the autoload.

It probably could use the same lock; the trickier bit is that in between
encountering the autoload and requiring the file there's already state
changes happening. So I think we still need to ensure the autoload
marker is mutated under lock as well.

To be honest, I'm not sure autoload is really even possible to make safe
in the presence of threads...the design of it may be inherently
incompatible. But I'm willing to talk through some possibilities and see
what we can come up with.

=end

Actions #3

Updated by pragdave (Dave Thomas) about 15 years ago

=begin

On Dec 22, 2008, at 1:44 PM, Charles Oliver Nutter wrote:

It probably could use the same lock; the trickier bit is that in
between encountering the autoload and requiring the file there's
already state changes happening. So I think we still need to ensure
the autoload marker is mutated under lock as well.

To be honest, I'm not sure autoload is really even possible to make
safe in the presence of threads...the design of it may be inherently
incompatible. But I'm willing to talk through some possibilities and
see what we can come up with.

Yeah--you'd need to make require transactional somehow.

Stupid question: does anyone actually use autoload?

Dave

=end

Actions #4

Updated by drbrain (Eric Hodel) about 15 years ago

=begin
On Dec 23, 2008, at 05:53 AM, Dave Thomas wrote:

On Dec 22, 2008, at 1:44 PM, Charles Oliver Nutter wrote:

It probably could use the same lock; the trickier bit is that in
between encountering the autoload and requiring the file there's
already state changes happening. So I think we still need to ensure
the autoload marker is mutated under lock as well.

To be honest, I'm not sure autoload is really even possible to make
safe in the presence of threads...the design of it may be
inherently incompatible. But I'm willing to talk through some
possibilities and see what we can come up with.

Yeah--you'd need to make require transactional somehow.

Stupid question: does anyone actually use autoload?

RubyGems now does, but the code wasn't introduced by me.

=end

Actions #5

Updated by rogerdpack (Roger Pack) about 15 years ago

=begin

Currently autoload is not safe to use in a multi-threaded application.

My preference would be for it at most one thread to be "in an
autoload" at a time, so similar to require, no chance for confusion.
But then again that's just me :)

-r-

=end

Actions #6

Updated by austin (Austin Ziegler) about 15 years ago

=begin
On Tue, Dec 23, 2008 at 3:51 PM, Christian Neukirchen
wrote:

Dave Thomas writes:

On Dec 22, 2008, at 1:44 PM, Charles Oliver Nutter wrote:

It probably could use the same lock; the trickier bit is that in
between encountering the autoload and requiring the file there's
already state changes happening. So I think we still need to ensure
the autoload marker is mutated under lock as well.

To be honest, I'm not sure autoload is really even possible to make
safe in the presence of threads...the design of it may be inherently
incompatible. But I'm willing to talk through some possibilities and
see what we can come up with.

Yeah--you'd need to make require transactional somehow.

Stupid question: does anyone actually use autoload?

Rack does. Merb does as well.

So does RbGCCXML, a random library that I'm using (I see no point as
to why it's doing so, to be honest).

-austin

Austin Ziegler * * http://www.halostatue.ca/
* * http://www.halostatue.ca/feed/
*

=end

Actions #7

Updated by headius (Charles Nutter) about 15 years ago

=begin
Dave Thomas wrote:

To be honest, I'm not sure autoload is really even possible to make
safe in the presence of threads...the design of it may be inherently
incompatible. But I'm willing to talk through some possibilities and
see what we can come up with.

Yeah--you'd need to make require transactional somehow.

Yeah, that's essentially it (though it's more specific to autoload).
You'd need to lock the constant under autoload in such a way that other
threads would block until autoloading completed. And unless it were a
single global lock for all autoload logic, there's a strong potential
for deadlock if two threads encounter opposing constants at the same time.

Stupid question: does anyone actually use autoload?

They do, but they probably shouldn't. It's broken.

=end

Actions #8

Updated by pragdave (Dave Thomas) about 15 years ago

=begin

On Dec 23, 2008, at 4:16 PM, Charles Oliver Nutter wrote:

Yeah--you'd need to make require transactional somehow.

Yeah, that's essentially it (though it's more specific to autoload).
You'd need to lock the constant under autoload in such a way that
other threads would block until autoloading completed. And unless it
were a single global lock for all autoload logic, there's a strong
potential for deadlock if two threads encounter opposing constants
at the same time.

Would it be sufficient to add field to each constant to say "loading
in progress in thread n"

Have the lock we've been talking about in autoload and require.

During require, set the current thread id into every newly defined
constant, keeping a list of the ones that are set. Maintain a stack of
the current requires. (These will all be in the same thread because of
the mutex).

When the last require finishes, go though all constants in the list
and unset the thread id in them. Finally, signal a condition variable.

Constant lookup then works like this: If the constant isn't defined,
claim the require mutex and then check for autoloading stuff.

If the constant is defined, check to see if the thread id is set in
the constant. If it is, wait on the condition variable. That way, you
won't pick up partially initialized constants that are being
autoloaded or required by other threads.

And, I know, this sounds ridiculously complex. But the only
alternative I see is locking the entire interpreter during requires.

Dave

=end

Actions #9

Updated by nobu (Nobuyoshi Nakada) about 15 years ago

=begin
Hi,

At Tue, 23 Dec 2008 02:10:34 +0900,
Charles Nutter wrote in [ruby-core:20797]:

The current logic for autoload is as follows:

This description is old. Already autoload sees the same lock
used by require, as Dave Thomas mentioned in [ruby-core:20801].

So I guess the autoload specific issue has gone, and we could
focus on the issue of recursive/circular require, i.e.,
[ruby-core:20794].

--
Nobu Nakada

=end

Actions #10

Updated by headius (Charles Nutter) about 15 years ago

=begin
Nobuyoshi Nakada wrote:

Hi,

At Tue, 23 Dec 2008 02:10:34 +0900,
Charles Nutter wrote in [ruby-core:20797]:

The current logic for autoload is as follows:

This description is old. Already autoload sees the same lock
used by require, as Dave Thomas mentioned in [ruby-core:20801].

So I guess the autoload specific issue has gone, and we could
focus on the issue of recursive/circular require, i.e.,
[ruby-core:20794].

So if two threads lookup the same autoload constant at the same time, is
the second thread guaranteed to wait until the first thread has finished
requiring?

I was not aware this had been fixed or decided.

=end

Actions #11

Updated by nobu (Nobuyoshi Nakada) about 15 years ago

=begin
Hi,

At Wed, 24 Dec 2008 14:56:37 +0900,
Charles Oliver Nutter wrote in [ruby-core:20853]:

So I guess the autoload specific issue has gone, and we could
focus on the issue of recursive/circular require, i.e.,
[ruby-core:20794].

So if two threads lookup the same autoload constant at the same time, is
the second thread guaranteed to wait until the first thread has finished
requiring?

It's same as two threads requiring without autoloading.

--
Nobu Nakada

=end

Actions #12

Updated by headius (Charles Nutter) about 15 years ago

=begin
Nobuyoshi Nakada wrote:

It's same as two threads requiring without autoloading.

I'm not sure this is safe enough. If the first thread has already set
the constant, the second thread would not know it is an autoload and
would return its value immediately. The resource the constant points at
may not be done loading.

my_file.rb:

module XXX
class Foo
# HERE
def bar; ... end
end
end

my_autoload.rb:

module XXX
autoload :Foo, "my_file.rb"
end

Thread 1

Thread.new { XXX::Foo.new.bar }

Thread 2

Thread.new { XXX::Foo.new.bar }

Thread 1 tries to look up XXX::Foo and starts requiring my_file.rb. It
reaches # HERE above and the XXX::Foo constant now points at the Foo
class. Now thread 2 looks up XXX::Foo, and since it is not an autoload
marker it gets the incomplete Foo class. Thread 2 blows up when it tries
to call bar because bar is not yet defined.

=end

Actions #13

Updated by stepheneb (Stephen Bannasch) about 15 years ago

=begin
At 10:53 PM +0900 12/23/08, Dave Thomas wrote:

Stupid question: does anyone actually use autoload?

Since the 2.2.2 release the rails trunk codebase has been doing a mass replacement of require with autoload.
=end

Actions #14

Updated by shyouhei (Shyouhei Urabe) about 15 years ago

  • Assignee set to nobu (Nobuyoshi Nakada)
  • ruby -v set to -

=begin

=end

Actions #15

Updated by nobu (Nobuyoshi Nakada) over 14 years ago

  • Status changed from Open to Closed

=begin

=end

Updated by nahi (Hiroshi Nakamura) almost 13 years ago

Sorry for commenting this dated ticket.

Charles: I agree with Nobu that it's not autoload specific issue but a thereaded require issue.

my_file.rb:

module XXX
class Foo
# HERE
def bar; ... end
end
end

my_load.rb:

Thread 1

Thread.new { require 'my_file'; XXX::Foo.new.bar }

Thread 2

Thread.new { XXX::Foo.new.bar }

Thread 2 can get NoMethodError(for bar) instead of NameError(for XXX) I think and it's Ruby's behavior at this moment.

I'm just commenting this for closing similar ticket of JRuby: http://jira.codehaus.org/browse/JRUBY-3194. Sorry for the noise.

Updated by headius (Charles Nutter) almost 13 years ago

The concurrent require issue is separate. I would like to understand what 1.9.3 does to make concurrent requires safe. A global lock around any require? I know there was a lock against specific filenames added at some point (which JRuby also does)...is there something more?

I do not understand how the autoload problem was fixed. Here is a simpler example...

autoload.rb:

class Object
autoload :X, 'constant.rb'
end

Thread.abort_on_exception = true

Thread.new {
puts "thread #{Thread.current} accessing X; defined? X == #{(defined? X).inspect}"
X
}
Thread.new {
puts "thread #{Thread.current} accessing X; defined? X == #{(defined? X).inspect}"
X
}
sleep

constant.rb:

simulate a slow file load or a deep chain of requires

puts "thread #{Thread.current} in constant.rb"

check that X is not defined

puts "X defined: #{(defined? X).inspect}"

1_000_000.times { Thread.pass }

class Object

define X

X = 1
end

I will review the problem.

When autoloading is triggered, the first step is to remove the autoload constant. This allows the file being required to see a blank slate when (presumably) defining the constant attached to autoloading. The above example does indeed print out "X defined: nil".

Now if we have two threads that encounter an autoloaded constant at roughly the same time, I would expect this sequence is possible:

For our autoloaded constant X:

  1. Thread A encounters the autoload for X and removes the constant. It proceeds to require the associated file which (eventually) will define X.
  2. Because thread A is now in Ruby code, a context switch can occur to thread B.
  3. Thread B attempts to access the autoloaded constant X; however it has been removed by A, and thread B gets a NameError. It does not wait for the require to complete, because it never attempts to perform a require.

This is what happens in JRuby, Rubinius, and Ruby 1.8.7. It does not happen in Ruby 1.9.2 or MacRuby. Why?

Here is the output under 1.8.7:

~/projects/jruby ➔ ruby autoload.rb
thread #Thread:0x100169dc8 accessing X; defined? X == "constant"
thread #Thread:0x100169dc8 in constant.rb
X defined: nil
thread #Thread:0x100169080 accessing X; defined? X == nil
autoload.rb:13: uninitialized constant X (NameError)
from autoload.rb:11:in initialize' from autoload.rb:11:in new'
from autoload.rb:11

What appears to happen is that thread B encounters the X autoload and pauses. This could be explained for concurrent requires of the same file (if synchronizing against a filename), or for concurrent requires of different files (if there's a single global lock) but that still does not explain why autoload behaves this way in 1.9.2. Why? Because if thread A is actually removing the constant, it should never know that it's an autoload constant and should fail to block on a require lock of any kind. And it does appear that the constant has been removed...so how does thread B know to pause?

I could dig through the MRI code to find this, but perhaps can someone describe in simple terms how 1.9.2 prevents thread B in the example above from running when it encounters X?

Updated by nahi (Hiroshi Nakamura) almost 13 years ago

Thanks. I've understand the issue is separated. The problem is not for method definition bar as you wrote in the previous example but for constant definition.

Anyway it looks fixed for CRuby, I'll back to http://jira.codehaus.org/browse/JRUBY-3194. The patch posted to JRUBY-3194 still doesn't solve the problem. Sigh.

Updated by nahi (Hiroshi Nakamura) almost 13 years ago

  • Status changed from Closed to Open
  • Assignee changed from nobu (Nobuyoshi Nakada) to shyouhei (Shyouhei Urabe)
  • ruby -v changed from - to ruby 1.8.7 (2011-02-18 patchlevel 334) [x86_64-linux]

For JRuby 1.9, I fixed this issue (autoload thread safety.)

Regards to autoload, CRuby 1.9 is thread-safe. CRuby 1.8 is not thread-safe.

% cat autoload.rb
class Foo
autoload :X, 'constant.rb'
end

Thread.abort_on_exception = true

t1 = Thread.new {
puts "thread #{Thread.current} accessing X"
p Foo::X
}
t2 = Thread.new {
puts "thread #{Thread.current} accessing X"
p Foo::X
}

t1.join
t2.join

% cat constant.rb

simulate a slow file load or a deep chain of requires

puts "#{Thread.current} in constant.rb"

1_000_000.times { Thread.pass }

class Foo
# define X
X = 1
end

% ruby187 autoload.rb
thread #Thread:0x7f2e2e301de0 accessing X
#Thread:0x7f2e2e301de0 in constant.rb
thread #Thread:0x7f2e2e301390 accessing X
autoload.rb:13: uninitialized constant Foo::X (NameError)
from autoload.rb:11:in initialize' from autoload.rb:11:in new'
from autoload.rb:11
zsh: exit 1 ruby187 autoload.rb

After talking to Shyouhei at Asakusa.rb meetup last night, we agreed that
it's a bug and it should be fixed if we can.

And here's another problem arises. 1.8 removes autoload a constant first as
Charles stated above, then requires the specified file. It's the cause of
threaded autoload issue but it has another side effect. When the require fails
with some Exception, the defined constant is removed afterwards.

% ruby187 -I. -e 'autoload(:X, "X"); begin; X; rescue LoadError; end; p Object.constants.include?("X")'
false

1.9 does not remove the constant.

% ruby -I. -e 'autoload(:X, "X"); begin; X; rescue LoadError; end; p Object.constants.include?(:X)'
true

I'm guessing this behavior would be affected when we fix 1.8's thread safety.
Unfortunately, there're "spec"s in RubySpec which expects that constant to be
removed in 1.8.

Can we change this 1.8.7 behavior?

Updated by nahi (Hiroshi Nakamura) almost 13 years ago

FYI: shyouhei is working for the fix. Here's commits for ruby_1_8 branch.
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?revision=31732&view=revision
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?revision=31734&view=revision
And a little modification for ruby_1_8_7 adjustment by me.
https://gist.github.com/992380

This patch intends;

  • do not remove an autoload constant before autoloading.
  • additional stop condition for edge case; when autoloading does not define the constant.

As I wrote above, this fix changes the following behavior.

% ruby187 -I. -e 'autoload(:X, "X"); begin; X; rescue LoadError; end; p Object.constants.include?("X")'
false #=> true like 1.9

Ruby developers, please let us know if you have any thoughts on this change.
With JRuby dev hat, I think it's OK. How other Ruby impls devs think?

Actions #21

Updated by akr (Akira Tanaka) over 12 years ago

  • Project changed from Ruby to Ruby master

Updated by nahi (Hiroshi Nakamura) over 12 years ago

  • Assignee changed from shyouhei (Shyouhei Urabe) to nahi (Hiroshi Nakamura)
  • Target version set to 2.0.0

I discussed this with Shyouhei, Sasada, Tanaka and Naruse. And we don't have a consensus.

Updated by nahi (Hiroshi Nakamura) over 12 years ago

  • Category set to core

(Still no progress, just adding a note for future work)

I proposed the fix for JRuby at http://bit.ly/npPi66 (http://jira.codehaus.org/browse/JRUBY-3194)
And I had a talk about this issue in front of other Japanese CRuby committers last night.
http://prezi.com/ff9yptxhohjz/making-autoload-thread-safe/

As the result of discussing, we are going to fix CRuby as the same way.

Updated by nahi (Hiroshi Nakamura) over 12 years ago

I created a patch: https://github.com/nahi/ruby/compare/48bc63fa...54327abc
Here's the branch: https://github.com/nahi/ruby/commits/autoload-threadsafe

  • let Module keep 'UNDEF' in constant map until the end of autoloading
  • let Module keep actual object in another map (autoloading map)
  • add extra checks for constant looku

Updated by nahi (Hiroshi Nakamura) over 12 years ago

Updated the patch: https://github.com/nahi/ruby/compare/11667b9c...8b78a18e
Rewritten with strust instead of st_table.

Updated by nahi (Hiroshi Nakamura) over 12 years ago

=begin

Here's the updated patch: [https://github.com/nahi/ruby/compare/11667b9c...03ddf439]

Summary

  • ((What's the problem?)) autoload is thread unsafe. When we define a constant to be autoloaded, we expect the constant construction is invariant. But current autoload implementation allows other threads to access the constant while the first thread is loading a file. See http://prezi.com/ff9yptxhohjz/making-autoload-thread-safe/ for an example.

  • ((What's happening inside?)) The current implementation uses Qundef as a marker of autoload in Constant table. Once the first thread find Qundef as a value at constant lookup, it starts loading a defined feature. Generally a loaded file overrides the Qundef in Constant table by module/class declaration at very beginning lines of the file, so other threads can see the new Module/Class object before feature loading is finished. It breaks invariant construction.

  • ((How to solve?)) To ensure invariant constant construction, we need to override Qundef with defined Object after the feature loading. For keeping Qundef in Constant table, I expanded autoload_data struct in Module to have a slot for keeping the defined object while feature loading. And changed Module's constant lookup/update logic a little so that the slot is only visible from the thread which invokes feature loading. (== the first thread which accessed the autoload constant)

  • ((Evaluation?)) All test passes (bootstrap test, test-all and RubySpec) and added 8 tests for threading behavior. Extra logics are executed only when Qundef is found, so no perf drop should happen except autoloading.

I'll commit this soon. Committers, please evaluate this.
=end

Updated by normalperson (Eric Wong) over 12 years ago

Hiroshi Nakamura wrote:

I'll commit this soon. Committers, please evaluate this.

I noticed this got committed (r33078) and reverted (r33093).
Is a better commit planned? Thanks for working on this!

Updated by nahi (Hiroshi Nakamura) over 12 years ago

  • ruby -v changed from ruby 1.8.7 (2011-02-18 patchlevel 334) [x86_64-linux] to -

On Tue, Aug 30, 2011 at 07:14, Eric Wong wrote:

Hiroshi Nakamura wrote:

I'll commit this soon. Committers, please evaluate this.

I noticed this got committed (r33078) and reverted (r33093).
Is a better commit planned?  Thanks for working on this!

Yes, it broke Rails X-( I forgot a path to invoke rb_autoload_load
from insns.def.

I fixed it my local repo but I need to ensure it passes Rails test
before committing it. :)

Thanks for your concern!

Updated by nahi (Hiroshi Nakamura) over 12 years ago

Hmm. Updating via reply e-mail seems to remove 'ruby -v'...

Updated by nahi (Hiroshi Nakamura) over 12 years ago

I re-apply r33078 and additional fixes at r33147. I tested it against Rails 3.1.0 and confirmed that it passes all of full tests except PG/MySQL/SQLite things which I don't installed properly.

Please evaluate it!

P.S. It won't included in 1.9.3 GA, but tell me if you find autoload threading issues on 193 as well, since RubyGems, RDoc, etc starts using autoload from 193. I think there's a chance to backport it. :)

Updated by normalperson (Eric Wong) over 12 years ago

Hiroshi Nakamura wrote:

I re-apply r33078 and additional fixes at r33147. I tested it against
Rails 3.1.0 and confirmed that it passes all of full tests except
PG/MySQL/SQLite things which I don't installed properly.

Please evaluate it!

I got the following with r33147 on gcc (Debian 4.6.1-4) 4.6.1:

../variable.c: In function ‘autoload_defined_p’:
../variable.c:1613:5: error: implicit declaration of function ‘rb_autoloading_value’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors

Moving the definition of autoload_defined_p() after the definition of
rb_autoloading_value() trivially fixes my build:

--- a/variable.c
+++ b/variable.c
@@ -1601,18 +1601,6 @@ check_autoload_required(VALUE mod, ID id, const char **loadingpath)
return 0;
}

-static int
-autoload_defined_p(VALUE mod, ID id)
-{

  • struct st_table *tbl = RCLASS_CONST_TBL(mod);
  • st_data_t val;
  • if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) {
  • return 0;
  • }
  • return !rb_autoloading_value(mod, id, NULL);
    -}

int
rb_autoloading_value(VALUE mod, ID id, VALUE* value)
{
@@ -1633,6 +1621,18 @@ rb_autoloading_value(VALUE mod, ID id, VALUE* value)
return 0;
}

+static int
+autoload_defined_p(VALUE mod, ID id)
+{

  • struct st_table *tbl = RCLASS_CONST_TBL(mod);
  • st_data_t val;
  • if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) {
  • return 0;
  • }
  • return !rb_autoloading_value(mod, id, NULL);
    +}

struct autoload_const_set_args {
VALUE mod;
ID id;

Eric Wong

Updated by nahi (Hiroshi Nakamura) over 12 years ago

Eric Wong wrote:

I got the following with r33147 on gcc (Debian 4.6.1-4) 4.6.1:

../variable.c: In function ‘autoload_defined_p’:
../variable.c:1613:5: error: implicit declaration of function ‘rb_autoloading_value’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors

Moving the definition of autoload_defined_p() after the definition of
rb_autoloading_value() trivially fixes my build:
[snip]

NARUSE-san applied this at r33151. Thank, guys!

Updated by nahi (Hiroshi Nakamura) over 12 years ago

  • Status changed from Open to Closed
  • Target version changed from 2.0.0 to 1.9.4

Closing. Please reopen this ticket if you find any regression.

Updated by Nevir (Ian MacLeod) about 11 years ago

Apologies in advance if this is the wrong place to get clarification:

It's been widely circulated that autoload is deprecated - http://www.ruby-forum.com/topic/3036681 - does this patch change that stance?

I ask because autoload still appears to be the best route for libraries to avoid heavy load times; especially now that it is thread safe in JRuby and MRI.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0