@@ -573,18 +573,18 @@ func (s *arduinoCoreServerImpl) runProgramAction(ctx context.Context, pme *packa
573573 // Run recipes for upload
574574 toolEnv := pme .GetEnvVarsForSpawnedProcess ()
575575 if burnBootloader {
576- if err := runTool ("erase.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
576+ if err := runTool (uploadCtx , "erase.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
577577 return nil , & cmderrors.FailedUploadError {Message : i18n .Tr ("Failed chip erase" ), Cause : err }
578578 }
579- if err := runTool ("bootloader.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
579+ if err := runTool (uploadCtx , "bootloader.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
580580 return nil , & cmderrors.FailedUploadError {Message : i18n .Tr ("Failed to burn bootloader" ), Cause : err }
581581 }
582582 } else if programmer != nil {
583- if err := runTool ("program.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
583+ if err := runTool (uploadCtx , "program.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
584584 return nil , & cmderrors.FailedUploadError {Message : i18n .Tr ("Failed programming" ), Cause : err }
585585 }
586586 } else {
587- if err := runTool ("upload.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
587+ if err := runTool (uploadCtx , "upload.pattern" , uploadProperties , outStream , errStream , verbose , dryRun , toolEnv ); err != nil {
588588 return nil , & cmderrors.FailedUploadError {Message : i18n .Tr ("Failed uploading" ), Cause : err }
589589 }
590590 }
@@ -702,7 +702,12 @@ func detectUploadPort(
702702 }
703703}
704704
705- func runTool (recipeID string , props * properties.Map , outStream , errStream io.Writer , verbose bool , dryRun bool , toolEnv []string ) error {
705+ func runTool (ctx context.Context , recipeID string , props * properties.Map , outStream , errStream io.Writer , verbose bool , dryRun bool , toolEnv []string ) error {
706+ // if ctx is already canceled just exit
707+ if err := ctx .Err (); err != nil {
708+ return err
709+ }
710+
706711 recipe , ok := props .GetOk (recipeID )
707712 if ! ok {
708713 return errors .New (i18n .Tr ("recipe not found '%s'" , recipeID ))
@@ -739,6 +744,17 @@ func runTool(recipeID string, props *properties.Map, outStream, errStream io.Wri
739744 return errors .New (i18n .Tr ("cannot execute upload tool: %s" , err ))
740745 }
741746
747+ // If the ctx is canceled, kill the running command
748+ completed := make (chan struct {})
749+ defer close (completed )
750+ go func () {
751+ select {
752+ case <- ctx .Done ():
753+ _ = cmd .Kill ()
754+ case <- completed :
755+ }
756+ }()
757+
742758 if err := cmd .Wait (); err != nil {
743759 return errors .New (i18n .Tr ("uploading error: %s" , err ))
744760 }
0 commit comments