Skip to content

Why did/does disable-optimize expose a hidden infinite loop #6179

Closed
@pnkfelix

Description

@pnkfelix

This is spawned off of Issues #6061 and #6049

Those were bugs were some developers could not bootstrap Rust because it was hitting stack exhaustion issues during the bootstrap process. The stack exhaustion was due to an infinite loop in a core routine. However, the curious question is why that core routine was not being invoked uniformly for all builds.

From my attempts to isolate the problem (see notes on #6061), it appears like the behavior of the binaries generated by configure --disable-optimize have significant semantically-visible differences from binaries generated by configure.

We have since plugged in a fix for the infinite loop in the core routine, so that everyone can bootstrap and we're all happy. Except we're not, because there's still a bug here that was exposed by the infinite loop (namely the difference when you toggle --disable-optimize) and was not fixed when the infinite loop was fixed.

There are at least two ways to go about reproducing this problem at this stage (where we have not narrowed it down too much). The first and most robust way is to actually check out the code from the commit where this bug was encountered and before it the infinite loop was removed, say for example SHA: 1d53bab
(The problem with that strategy is that if the underlying bug gets fixed in the meantime by someone else, you might not know it, and waste a lot of time investigating an issue that has since been resolved.)

The second way to reproduce the problem is to revert the fix to the infinite loop (which is a tiny patch) and then attempt a bootstrap build with and without --disable-optimize. I demonstrate that strategy here:

% git diff
diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs
index 80f69f0..8b77539 100644
--- a/src/libcore/rand.rs
+++ b/src/libcore/rand.rs
@@ -843,7 +843,7 @@ pub fn task_rng() -> @IsaacRng {
 // Allow direct chaining with `task_rng`
 impl<R: Rng> Rng for @R {
     #[inline(always)]
-    fn next(&self) -> u32 { (**self).next() }
+    fn next(&self) -> u32 { (*self).next() }
 }

 /**
% mkdir objdir-default
% mkdir objdir-dis-opt
% cd objdir-default/
% ../configure > ../invoke-config-default.log
sed: 1: "tools/Makefile": undefined label 'ools/Makefile'
% make rustc-stage1 -j4 >> ../invoke-make-default.log 2>&1
% cd ../objdir-dis-opt/
% ../configure --disable-optimize > ../invoke-config-dis-opt.log
sed: 1: "tools/Makefile": undefined label 'ools/Makefile'
% make rustc-stage1 -j4 > ../invoke-make-dis-opt.log  2>&1
[ERROR#1] % tail ../invoke-make-dis-opt.log
                                                         ^~~~~
warning: no debug symbols in executable (-arch x86_64)
compile_and_link: x86_64-apple-darwin/stage0/lib/rustc/x86_64-apple-darwin/bin/rustc
cp: x86_64-apple-darwin/stage1/lib/librustc.dylib
warning: no debug symbols in executable (-arch x86_64)
cp: x86_64-apple-darwin/stage1/bin/rustc
compile_and_link: x86_64-apple-darwin/stage1/lib/rustc/x86_64-apple-darwin/lib/libcore.dylib
rust: task 7ff2a040ac80 ran out of stack
/bin/sh: line 1: 80249 Abort trap: 6           x86_64-apple-darwin/stage1/bin/rustc --cfg stage1 --target=x86_64-apple-darwin -o x86_64-apple-darwin/stage1/lib/rustc/x86_64-apple-darwin/lib/libcore.dylib /tmp/rust/src/libcore/core.rc
make: *** [x86_64-apple-darwin/stage1/lib/rustc/x86_64-apple-darwin/lib/libcore.dylib] Error 134
% 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions