@@ -53,6 +53,7 @@ use std::time::{
5353 Instant ,
5454} ;
5555use tempdir:: TempDir ;
56+ use tokio_core:: reactor:: { Handle , Timeout } ;
5657
5758use errors:: * ;
5859
@@ -174,6 +175,8 @@ pub enum MissType {
174175 Normal ,
175176 /// Cache lookup was overridden, recompilation was forced.
176177 ForcedRecache ,
178+ /// Cache took too long to respond.
179+ TimedOut ,
177180}
178181
179182/// Information about a successful cache write.
@@ -298,7 +301,8 @@ impl Compiler {
298301 parsed_args : & ParsedArguments ,
299302 cwd : & str ,
300303 cache_control : CacheControl ,
301- pool : & CpuPool )
304+ pool : & CpuPool ,
305+ handle : & Handle )
302306 -> SFuture < ( CompileResult , process:: Output ) >
303307 where T : CommandCreatorSync
304308 {
@@ -319,6 +323,7 @@ impl Compiler {
319323 let storage = storage. clone ( ) ;
320324 let pool = pool. clone ( ) ;
321325 let creator = creator. clone ( ) ;
326+ let handle = handle. clone ( ) ;
322327
323328 Box :: new ( result. and_then ( move |preprocessor_result| -> SFuture < _ > {
324329 // If the preprocessor failed, just return that result.
@@ -355,6 +360,20 @@ impl Compiler {
355360 storage. get ( & key)
356361 } ;
357362
363+ // Wait at most a minute for the cache to respond before we forge
364+ // ahead ourselves with a compilation.
365+ let timeout = Duration :: new ( 60 , 0 ) ;
366+ let timeout = Timeout :: new ( timeout, & handle) . into_future ( ) . flatten ( ) ;
367+
368+ let cache_status = cache_status. map ( Some ) ;
369+ let timeout = timeout. map ( |_| None ) . chain_err ( || "timeout error" ) ;
370+ let cache_status = cache_status. select ( timeout) . then ( |r| {
371+ match r {
372+ Ok ( ( a, _other) ) => Ok ( a) ,
373+ Err ( ( e, _other) ) => Err ( e) ,
374+ }
375+ } ) ;
376+
358377 Box :: new ( cache_status. and_then ( move |result| {
359378 let duration = start. elapsed ( ) ;
360379 let pwd = Path :: new ( & cwd) ;
@@ -363,7 +382,7 @@ impl Compiler {
363382 . collect :: < HashMap < _ , _ > > ( ) ;
364383
365384 let miss_type = match result {
366- Cache :: Hit ( mut entry) => {
385+ Some ( Cache :: Hit ( mut entry) ) => {
367386 debug ! ( "[{}]: Cache hit!" , parsed_args. output_file( ) ) ;
368387 let mut stdout = io:: Cursor :: new ( vec ! ( ) ) ;
369388 let mut stderr = io:: Cursor :: new ( vec ! ( ) ) ;
@@ -386,14 +405,18 @@ impl Compiler {
386405 ( result, output)
387406 } ) ) as SFuture < _ >
388407 }
389- Cache :: Miss => {
408+ Some ( Cache :: Miss ) => {
390409 debug ! ( "[{}]: Cache miss!" , parsed_args. output_file( ) ) ;
391410 MissType :: Normal
392411 }
393- Cache :: Recache => {
412+ Some ( Cache :: Recache ) => {
394413 debug ! ( "[{}]: Cache recache!" , parsed_args. output_file( ) ) ;
395414 MissType :: ForcedRecache
396415 }
416+ None => {
417+ debug ! ( "[{}]: Cache timed out!" , parsed_args. output_file( ) ) ;
418+ MissType :: TimedOut
419+ }
397420 } ;
398421 me. compile ( & creator,
399422 preprocessor_result,
@@ -662,6 +685,7 @@ mod test {
662685 use std:: time:: Duration ;
663686 use std:: usize;
664687 use test:: utils:: * ;
688+ use tokio_core:: reactor:: Core ;
665689
666690 #[ test]
667691 fn test_detect_compiler_kind_gcc ( ) {
@@ -742,6 +766,8 @@ mod test {
742766 let creator = new_creator ( ) ;
743767 let f = TestFixture :: new ( ) ;
744768 let pool = CpuPool :: new ( 1 ) ;
769+ let core = Core :: new ( ) . unwrap ( ) ;
770+ let handle = core. handle ( ) ;
745771 let storage = DiskCache :: new ( & f. tempdir . path ( ) . join ( "cache" ) ,
746772 usize:: MAX ,
747773 & pool) ;
@@ -778,7 +804,8 @@ mod test {
778804 & parsed_args,
779805 cwd,
780806 CacheControl :: Default ,
781- & pool) . wait ( ) . unwrap ( ) ;
807+ & pool,
808+ & handle) . wait ( ) . unwrap ( ) ;
782809 // Ensure that the object file was created.
783810 assert_eq ! ( true , fs:: metadata( & obj) . and_then( |m| Ok ( m. len( ) > 0 ) ) . unwrap( ) ) ;
784811 match cached {
@@ -802,7 +829,8 @@ mod test {
802829 & parsed_args,
803830 cwd,
804831 CacheControl :: Default ,
805- & pool) . wait ( ) . unwrap ( ) ;
832+ & pool,
833+ & handle) . wait ( ) . unwrap ( ) ;
806834 // Ensure that the object file was created.
807835 assert_eq ! ( true , fs:: metadata( & obj) . and_then( |m| Ok ( m. len( ) > 0 ) ) . unwrap( ) ) ;
808836 assert_eq ! ( CompileResult :: CacheHit ( Duration :: new( 0 , 0 ) ) , cached) ;
@@ -818,6 +846,8 @@ mod test {
818846 let creator = new_creator ( ) ;
819847 let f = TestFixture :: new ( ) ;
820848 let pool = CpuPool :: new ( 1 ) ;
849+ let core = Core :: new ( ) . unwrap ( ) ;
850+ let handle = core. handle ( ) ;
821851 let storage = DiskCache :: new ( & f. tempdir . path ( ) . join ( "cache" ) ,
822852 usize:: MAX ,
823853 & pool) ;
@@ -854,7 +884,8 @@ mod test {
854884 & parsed_args,
855885 cwd,
856886 CacheControl :: Default ,
857- & pool) . wait ( ) . unwrap ( ) ;
887+ & pool,
888+ & handle) . wait ( ) . unwrap ( ) ;
858889 // Ensure that the object file was created.
859890 assert_eq ! ( true , fs:: metadata( & obj) . and_then( |m| Ok ( m. len( ) > 0 ) ) . unwrap( ) ) ;
860891 match cached {
@@ -879,7 +910,8 @@ mod test {
879910 & parsed_args,
880911 cwd,
881912 CacheControl :: Default ,
882- & pool) . wait ( ) . unwrap ( ) ;
913+ & pool,
914+ & handle) . wait ( ) . unwrap ( ) ;
883915 // Ensure that the object file was created.
884916 assert_eq ! ( true , fs:: metadata( & obj) . and_then( |m| Ok ( m. len( ) > 0 ) ) . unwrap( ) ) ;
885917 assert_eq ! ( CompileResult :: CacheHit ( Duration :: new( 0 , 0 ) ) , cached) ;
@@ -895,6 +927,8 @@ mod test {
895927 let creator = new_creator ( ) ;
896928 let f = TestFixture :: new ( ) ;
897929 let pool = CpuPool :: new ( 1 ) ;
930+ let core = Core :: new ( ) . unwrap ( ) ;
931+ let handle = core. handle ( ) ;
898932 let storage = DiskCache :: new ( & f. tempdir . path ( ) . join ( "cache" ) ,
899933 usize:: MAX ,
900934 & pool) ;
@@ -935,7 +969,8 @@ mod test {
935969 & parsed_args,
936970 cwd,
937971 CacheControl :: Default ,
938- & pool) . wait ( ) . unwrap ( ) ;
972+ & pool,
973+ & handle) . wait ( ) . unwrap ( ) ;
939974 // Ensure that the object file was created.
940975 assert_eq ! ( true , fs:: metadata( & obj) . and_then( |m| Ok ( m. len( ) > 0 ) ) . unwrap( ) ) ;
941976 match cached {
@@ -956,7 +991,8 @@ mod test {
956991 & parsed_args,
957992 cwd,
958993 CacheControl :: ForceRecache ,
959- & pool) . wait ( ) . unwrap ( ) ;
994+ & pool,
995+ & handle) . wait ( ) . unwrap ( ) ;
960996 // Ensure that the object file was created.
961997 assert_eq ! ( true , fs:: metadata( & obj) . and_then( |m| Ok ( m. len( ) > 0 ) ) . unwrap( ) ) ;
962998 match cached {
@@ -978,6 +1014,8 @@ mod test {
9781014 let creator = new_creator ( ) ;
9791015 let f = TestFixture :: new ( ) ;
9801016 let pool = CpuPool :: new ( 1 ) ;
1017+ let core = Core :: new ( ) . unwrap ( ) ;
1018+ let handle = core. handle ( ) ;
9811019 let storage = DiskCache :: new ( & f. tempdir . path ( ) . join ( "cache" ) ,
9821020 usize:: MAX ,
9831021 & pool) ;
@@ -1002,7 +1040,8 @@ mod test {
10021040 & parsed_args,
10031041 cwd,
10041042 CacheControl :: Default ,
1005- & pool) . wait ( ) . unwrap ( ) ;
1043+ & pool,
1044+ & handle) . wait ( ) . unwrap ( ) ;
10061045 assert_eq ! ( cached, CompileResult :: Error ) ;
10071046 assert_eq ! ( exit_status( 1 ) , res. status) ;
10081047 // Shouldn't get anything on stdout, since that would just be preprocessor spew!
0 commit comments