44package main
55
66import (
7+ "compress/gzip"
78 "context"
89 "crypto/sha256"
910 "encoding/json"
@@ -36,6 +37,7 @@ import (
3637 "github.com/google/syzkaller/prog"
3738 _ "github.com/google/syzkaller/sys"
3839 "github.com/google/syzkaller/sys/targets"
40+ "golang.org/x/sync/errgroup"
3941)
4042
4143// This is especially slightly longer than syzkaller rebuild period.
@@ -831,15 +833,19 @@ func (mgr *Manager) uploadBuildAssets(buildInfo *dashapi.Build, assetFolder stri
831833 return ret , nil
832834}
833835
834- func (mgr * Manager ) httpGET (path string ) (resp * http.Response , err error ) {
836+ func (mgr * Manager ) httpGET (ctx context. Context , path string ) (resp * http.Response , err error ) {
835837 addr := mgr .managercfg .HTTP
836838 if addr != "" && addr [0 ] == ':' {
837839 addr = "127.0.0.1" + addr // in case addr is ":port"
838840 }
839841 client := & http.Client {
840842 Timeout : time .Hour ,
841843 }
842- return client .Get (fmt .Sprintf ("http://%s%s" , addr , path ))
844+ req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("http://%s%s" , addr , path ), nil )
845+ if err != nil {
846+ return nil , err
847+ }
848+ return client .Do (req )
843849}
844850
845851func (mgr * Manager ) uploadCoverReport () error {
@@ -859,13 +865,13 @@ func (mgr *Manager) uploadCoverReport() error {
859865 }
860866 defer buildSem .Signal ()
861867
862- resp , err := mgr .httpGET ("/cover" )
868+ resp , err := mgr .httpGET (context . Background (), "/cover" )
863869 if err != nil {
864870 return fmt .Errorf ("failed to get report: %w" , err )
865871 }
866872 defer resp .Body .Close ()
867873 if directUpload {
868- return uploadFile (mgr .cfg .CoverUploadPath , mgr .name + ".html" , resp .Body , mgr .cfg .PublishGCS )
874+ return uploadFile (context . Background (), nil , mgr .cfg .CoverUploadPath , mgr .name + ".html" , resp .Body , mgr .cfg .PublishGCS )
869875 }
870876 // Upload via the asset storage.
871877 newAsset , err := mgr .storage .UploadBuildAsset (resp .Body , mgr .name + ".html" ,
@@ -880,8 +886,8 @@ func (mgr *Manager) uploadCoverReport() error {
880886 return nil
881887}
882888
883- func (mgr * Manager ) uploadCoverJSONLToGCS (mgrSrc , gcsDest string , curTime time.Time , publish bool ,
884- f func (io.Writer , * json.Decoder ) error ) error {
889+ func (mgr * Manager ) uploadCoverJSONLToGCS (gcsClient gcs. Client , mgrSrc , gcsDest string , curTime time.Time ,
890+ publish , compress bool , f func (io.Writer , * json.Decoder ) error ) error {
885891 if ! mgr .managercfg .Cover || gcsDest == "" {
886892 return nil
887893 }
@@ -895,7 +901,8 @@ func (mgr *Manager) uploadCoverJSONLToGCS(mgrSrc, gcsDest string, curTime time.T
895901 }
896902 defer buildSem .Signal ()
897903
898- resp , err := mgr .httpGET (mgrSrc )
904+ eg , egCtx := errgroup .WithContext (context .Background ())
905+ resp , err := mgr .httpGET (egCtx , mgrSrc )
899906 if err != nil {
900907 return fmt .Errorf ("failed to httpGet %s: %w" , mgrSrc , err )
901908 }
@@ -908,36 +915,48 @@ func (mgr *Manager) uploadCoverJSONLToGCS(mgrSrc, gcsDest string, curTime time.T
908915 }
909916
910917 pr , pw := io .Pipe ()
911- defer pr .Close ()
912- go func () {
918+ eg .Go (func () error {
919+ defer pw .Close ()
920+ var w io.Writer
921+ w = pw
922+ if compress {
923+ gzw := gzip .NewWriter (pw )
924+ defer gzw .Close ()
925+ w = gzw
926+ }
913927 decoder := json .NewDecoder (resp .Body )
914928 for decoder .More () {
915- if err := f (pw , decoder ); err != nil {
916- pw .CloseWithError (fmt .Errorf ("callback: %w" , err ))
917- return
929+ if err := f (w , decoder ); err != nil {
930+ return fmt .Errorf ("callback: %w" , err )
918931 }
919932 }
920- pw .Close ()
921- }()
922- fileName := fmt .Sprintf ("%s/%s-%s-%d-%d.jsonl" ,
923- mgr .mgrcfg .DashboardClient ,
924- mgr .name , curTime .Format (time .DateOnly ),
925- curTime .Hour (), curTime .Minute ())
926- if err := uploadFile (gcsDest , fileName , pr , publish ); err != nil {
927- return fmt .Errorf ("failed to uploadFileGCS(): %w" , err )
928- }
929- return nil
933+ return nil
934+ })
935+ eg .Go (func () error {
936+ defer pr .Close ()
937+ fileName := fmt .Sprintf ("%s/%s-%s-%d-%d.jsonl" ,
938+ mgr .mgrcfg .DashboardClient ,
939+ mgr .name , curTime .Format (time .DateOnly ),
940+ curTime .Hour (), curTime .Minute ())
941+ if err := uploadFile (egCtx , gcsClient , gcsDest , fileName , pr , publish ); err != nil {
942+ return fmt .Errorf ("uploadFile: %w" , err )
943+ }
944+ return nil
945+ })
946+ return eg .Wait ()
930947}
931948
932949func (mgr * Manager ) uploadCoverStat (fuzzingMinutes int ) error {
933950 // Coverage report generation consumes and caches lots of memory.
934951 // In the syz-ci context report generation won't be used after this point,
935952 // so tell manager to flush report generator.
936953 curTime := time .Now ()
937- if err := mgr .uploadCoverJSONLToGCS ("/cover?jsonl=1&flush=1" ,
954+ if err := mgr .uploadCoverJSONLToGCS (nil ,
955+ "/cover?jsonl=1&flush=1" ,
938956 mgr .cfg .CoverPipelinePath ,
939957 curTime ,
940958 false ,
959+ false ,
941960 func (w io.Writer , dec * json.Decoder ) error {
942961 var covInfo cover.CoverageInfo
943962 if err := dec .Decode (& covInfo ); err != nil {
@@ -964,10 +983,12 @@ func (mgr *Manager) uploadCoverStat(fuzzingMinutes int) error {
964983}
965984
966985func (mgr * Manager ) uploadProgramsWithCoverage () error {
967- if err := mgr .uploadCoverJSONLToGCS ("/coverprogs?jsonl=1" ,
986+ if err := mgr .uploadCoverJSONLToGCS (nil ,
987+ "/coverprogs?jsonl=1" ,
968988 mgr .cfg .CoverProgramsPath ,
969989 time .Now (),
970990 mgr .cfg .PublishGCS ,
991+ true ,
971992 func (w io.Writer , dec * json.Decoder ) error {
972993 var programCoverage cover.ProgramCoverage
973994 if err := dec .Decode (& programCoverage ); err != nil {
@@ -994,7 +1015,7 @@ func (mgr *Manager) uploadCorpus() error {
9941015 return err
9951016 }
9961017 defer f .Close ()
997- return uploadFile (mgr .cfg .CorpusUploadPath , mgr .name + "-corpus.db" , f , mgr .cfg .PublishGCS )
1018+ return uploadFile (context . Background (), nil , mgr .cfg .CorpusUploadPath , mgr .name + "-corpus.db" , f , mgr .cfg .PublishGCS )
9981019}
9991020
10001021func (mgr * Manager ) uploadBenchData () error {
@@ -1012,15 +1033,15 @@ func (mgr *Manager) uploadBenchData() error {
10121033 return fmt .Errorf ("failed to open bench file: %w" , err )
10131034 }
10141035 defer f .Close ()
1015- err = uploadFile (mgr .cfg .BenchUploadPath + "/" + mgr .name ,
1036+ err = uploadFile (context . Background (), nil , mgr .cfg .BenchUploadPath + "/" + mgr .name ,
10161037 mgr .lastRestarted .Format ("2006-01-02_15h.json" ), f , false )
10171038 if err != nil {
10181039 return fmt .Errorf ("failed to upload the bench file: %w" , err )
10191040 }
10201041 return nil
10211042}
10221043
1023- func uploadFile (dstPath , name string , file io.Reader , publish bool ) error {
1044+ func uploadFile (ctx context. Context , gcsClient gcs. Client , dstPath , name string , file io.Reader , publish bool ) error {
10241045 URL , err := url .Parse (dstPath )
10251046 if err != nil {
10261047 return fmt .Errorf ("failed to parse upload path: %w" , err )
@@ -1030,13 +1051,16 @@ func uploadFile(dstPath, name string, file io.Reader, publish bool) error {
10301051 log .Logf (0 , "uploading %v to %v" , name , URLStr )
10311052 if strings .HasPrefix (URLStr , "http://" ) ||
10321053 strings .HasPrefix (URLStr , "https://" ) {
1033- return uploadFileHTTPPut (URLStr , file )
1054+ if gcsClient != nil {
1055+ return fmt .Errorf ("gcsClient is expected to be nil for the http* requests" )
1056+ }
1057+ return uploadFileHTTPPut (ctx , URLStr , file )
10341058 }
1035- return gcs .UploadFile (context . Background () , file , URLStr , gcs.UploadOptions {Publish : publish })
1059+ return gcs .UploadFile (ctx , file , URLStr , gcs.UploadOptions {Publish : publish , GCSClientMock : gcsClient })
10361060}
10371061
1038- func uploadFileHTTPPut (URL string , file io.Reader ) error {
1039- req , err := http .NewRequest ( http .MethodPut , URL , file )
1062+ func uploadFileHTTPPut (ctx context. Context , URL string , file io.Reader ) error {
1063+ req , err := http .NewRequestWithContext ( ctx , http .MethodPut , URL , file )
10401064 if err != nil {
10411065 return fmt .Errorf ("failed to create HTTP PUT request: %w" , err )
10421066 }
0 commit comments