Skip to content

Commit cd09c2b

Browse files
Flush executables to disk after linkage
A problem caused by not doing so in Chrome has been reported here: https://randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp/ File::sync_all() calls FlushFileBuffers() down the line, causing potentially unflushed buffers on high I/O-load systems to flush and prevent nasty non-reproducible bugs. The force-flush is only done on Windows and if the linker exited successfully Closes #48545
1 parent 9c9424d commit cd09c2b

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

src/librustc_trans/back/link.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ fn link_natively(sess: &Session,
692692
loop {
693693
i += 1;
694694
prog = time(sess, "running linker", || {
695-
exec_linker(sess, &mut cmd, tmpdir)
695+
exec_linker(sess, &mut cmd, out_filename, tmpdir)
696696
});
697697
let output = match prog {
698698
Ok(ref output) => output,
@@ -819,7 +819,7 @@ fn link_natively(sess: &Session,
819819
}
820820
}
821821

822-
fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
822+
fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: &Path)
823823
-> io::Result<Output>
824824
{
825825
// When attempting to spawn the linker we run a risk of blowing out the
@@ -867,7 +867,37 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
867867
fs::write(&file, &bytes)?;
868868
cmd2.arg(format!("@{}", file.display()));
869869
info!("invoking linker {:?}", cmd2);
870-
return cmd2.output();
870+
let output = cmd2.output();
871+
flush_linked_file(&output, out_filename)?;
872+
return output;
873+
874+
#[cfg(unix)]
875+
fn flush_linked_file(_: &io::Result<Output>, _: &Path) -> io::Result<()> {
876+
Ok(())
877+
}
878+
879+
#[cfg(windows)]
880+
fn flush_linked_file(command_output: &io::Result<Output>, out_filename: &Path)
881+
-> io::Result<()>
882+
{
883+
// On Windows, under high I/O load, output buffers are sometimes not flushed,
884+
// even long after process exit, causing nasty, non-reproducible output bugs.
885+
//
886+
// File::sync_all() calls FlushFileBuffers() down the line, which solves the problem.
887+
//
888+
// А full writeup of the original Chrome bug can be found at
889+
// randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp
890+
891+
if let &Ok(ref out) = command_output {
892+
if out.status.success() {
893+
if let Ok(of) = fs::File::open(out_filename) {
894+
of.sync_all()?;
895+
}
896+
}
897+
}
898+
899+
Ok(())
900+
}
871901

872902
#[cfg(unix)]
873903
fn command_line_too_big(err: &io::Error) -> bool {

0 commit comments

Comments
 (0)