Skip to content

Commit ca2f8fc

Browse files
committed
Handle UnexpectedEof from server by compiling locally
I believe this is possible to hit if the compilation takes quite a long time and times out the server itself. The server may shut down due to being idle while we're still connected and cause us to receive an `UnexpectedEof`.
1 parent cb53fc3 commit ca2f8fc

1 file changed

Lines changed: 46 additions & 32 deletions

File tree

src/commands.rs

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use number_prefix::{
3232
Prefixed,
3333
Standalone,
3434
};
35-
use protobuf::RepeatedField;
35+
use protobuf::{RepeatedField, ProtobufError};
3636
use protocol::{
3737
CacheStats,
3838
ClientRequest,
@@ -458,43 +458,57 @@ fn handle_compile_response<T>(mut creator: T,
458458
CompileResponse::CompileStarted(_) => {
459459
debug!("Server sent CompileStarted");
460460
// Wait for CompileFinished.
461-
let mut res = conn.read_one_response().chain_err(|| {
462-
//TODO: something better here?
463-
"error reading compile response from server"
464-
})?;
465-
if res.has_compile_finished() {
466-
trace!("Server sent CompileFinished");
467-
handle_compile_finished(res.take_compile_finished(),
468-
stdout, stderr)
469-
} else {
470-
bail!("unexpected response from server")
461+
match conn.read_one_response() {
462+
Ok(mut res) => {
463+
if res.has_compile_finished() {
464+
trace!("Server sent CompileFinished");
465+
return handle_compile_finished(res.take_compile_finished(),
466+
stdout, stderr)
467+
} else {
468+
bail!("unexpected response from server")
469+
}
470+
}
471+
472+
// Currently the shutdown behavior of the remote sccache server
473+
// is to wait at most N seconds for all active connections to
474+
// finish and then close everything. If we get unlucky and don't
475+
// get a response then we just forge ahead locally and run the
476+
// compilation ourselves.
477+
Err(ProtobufError::IoError(ref e))
478+
if e.kind() == io::ErrorKind::UnexpectedEof => {}
479+
480+
Err(e) => return Err(e).chain_err(|| {
481+
//TODO: something better here?
482+
"error reading compile response from server"
483+
})
471484
}
472485
}
473486
CompileResponse::UnhandledCompile(_) => {
474487
debug!("Server sent UnhandledCompile");
475-
//TODO: possibly capture output here for testing.
476-
let mut cmd = creator.new_command_sync(exe);
477-
cmd.args(&cmdline)
478-
.current_dir(cwd);
479-
if log_enabled!(Trace) {
480-
trace!("running command: {:?}", cmd);
481-
}
482-
let output = try!(core.run(run_input_output(cmd, None)));
483-
if !output.stdout.is_empty() {
484-
try!(stdout.write_all(&output.stdout));
485-
}
486-
if !output.stderr.is_empty() {
487-
try!(stderr.write_all(&output.stderr));
488-
}
489-
Ok(output.status.code().unwrap_or_else(|| {
490-
if let Some(sig) = status_signal(output.status) {
491-
println!("Compile terminated by signal {}", sig);
492-
}
493-
// Arbitrary.
494-
2
495-
}))
496488
}
489+
};
490+
491+
//TODO: possibly capture output here for testing.
492+
let mut cmd = creator.new_command_sync(exe);
493+
cmd.args(&cmdline)
494+
.current_dir(cwd);
495+
if log_enabled!(Trace) {
496+
trace!("running command: {:?}", cmd);
497497
}
498+
let output = try!(core.run(run_input_output(cmd, None)));
499+
if !output.stdout.is_empty() {
500+
try!(stdout.write_all(&output.stdout));
501+
}
502+
if !output.stderr.is_empty() {
503+
try!(stderr.write_all(&output.stderr));
504+
}
505+
Ok(output.status.code().unwrap_or_else(|| {
506+
if let Some(sig) = status_signal(output.status) {
507+
println!("Compile terminated by signal {}", sig);
508+
}
509+
// Arbitrary.
510+
2
511+
}))
498512
}
499513

500514
/// Send a `Compile` request to the sccache server `conn`, and handle the response.

0 commit comments

Comments
 (0)