diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2025-01-18 15:48:10 +0100 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2025-01-18 19:19:48 +0100 | 
| commit | 1ecc43458cd5c4f41fb23948c48e429e376704a5 (patch) | |
| tree | 8b9d54da2f9dcfaccb3024749e4254fae80097cc /src/Command | |
| parent | cbf936f3479172260261ba07a4ff0ca30ae1fe98 (diff) | |
Cancel jobs on user interrupt
Changelog: Properly cancel and clean up jobs on user interrupt
Diffstat (limited to 'src/Command')
| -rw-r--r-- | src/Command/Run.hs | 59 | 
1 files changed, 33 insertions, 26 deletions
| diff --git a/src/Command/Run.hs b/src/Command/Run.hs index c762335..945a4fd 100644 --- a/src/Command/Run.hs +++ b/src/Command/Run.hs @@ -4,6 +4,7 @@ module Command.Run (  import Control.Concurrent  import Control.Concurrent.STM +import Control.Exception  import Control.Monad  import Control.Monad.Reader @@ -68,25 +69,32 @@ cmdRun (RunCommand changeset) = do              T.replicate (8 + 50) " " :              map ((" "<>) . fitToLength 7 . textJobName) names -        statuses <- forM jobssets $ \jobset -> do -            let commit = jobsetCommit jobset -                shortCid = T.pack $ take 7 $ showCommitId $ commitId commit -                shortDesc = fitToLength 50 (commitDescription commit) -            case jobsetJobsEither jobset of -                Right jobs -> do -                    outs <- runJobs mngr commit jobs -                    let findJob name = snd <$> find ((name ==) . jobName . fst) outs -                    displayStatusLine tout shortCid (" " <> shortDesc) $ map findJob names -                    return $ map snd outs -                Left err -> do -                    void $ newLine tout $ -                        "\ESC[91m" <> shortCid <> "\ESC[0m" <> " " <> shortDesc <> " \ESC[91m" <> T.pack err <> "\ESC[0m" -                    return [] - -        -- wait for all jobs to complete -        atomically $ forM_ (concat statuses) $ \tvar -> do -            status <- readTVar tvar -            when (not $ jobStatusFinished status) retry +        threadCount <- newTVarIO (0 :: Int) +        let changeCount f = atomically $ do +                writeTVar threadCount . f =<< readTVar threadCount +        let waitForJobs = atomically $ do +                flip when retry . (0 <) =<< readTVar threadCount + +        handle @SomeException (\_ -> cancelAllJobs mngr) $ do +            forM_ jobssets $ \jobset -> do +                let commit = jobsetCommit jobset +                    shortCid = T.pack $ take 7 $ showCommitId $ commitId commit +                    shortDesc = fitToLength 50 (commitDescription commit) +                case jobsetJobsEither jobset of +                    Right jobs -> do +                        outs <- runJobs mngr commit jobs +                        let findJob name = snd <$> find ((name ==) . jobName . fst) outs +                        line <- newLine tout "" +                        mask $ \restore -> do +                            changeCount (+ 1) +                            void $ forkIO $ (>> changeCount (subtract 1)) $ +                                try @SomeException $ restore $ do +                                    displayStatusLine tout line shortCid (" " <> shortDesc) $ map findJob names +                    Left err -> do +                        void $ newLine tout $ +                            "\ESC[91m" <> shortCid <> "\ESC[0m" <> " " <> shortDesc <> " \ESC[91m" <> T.pack err <> "\ESC[0m" +            waitForJobs +        waitForJobs  fitToLength :: Int -> Text -> Text @@ -102,6 +110,7 @@ showStatus blink = \case      JobRunning      -> "\ESC[96m" <> (if blink then "*" else "•") <> "\ESC[0m      "      JobError _      -> "\ESC[91m!!\ESC[0m     "      JobFailed       -> "\ESC[91m✗\ESC[0m      " +    JobCancelled    ->  "\ESC[0mC\ESC[0m      "      JobDone _       -> "\ESC[92m✓\ESC[0m      "      JobDuplicate _ s -> case s of @@ -111,13 +120,11 @@ showStatus blink = \case          JobRunning   -> "\ESC[96m" <> (if blink then "*" else "^") <> "\ESC[0m      "          _            -> showStatus blink s -displayStatusLine :: TerminalOutput -> Text -> Text -> [ Maybe (TVar (JobStatus JobOutput)) ] -> IO () -displayStatusLine tout prefix1 prefix2 statuses = do -    line <- newLine tout "" -    void $ forkIO $ do -        go line "\0" +displayStatusLine :: TerminalOutput -> TerminalLine -> Text -> Text -> [ Maybe (TVar (JobStatus JobOutput)) ] -> IO () +displayStatusLine tout line prefix1 prefix2 statuses = do +    go "\0"    where -    go line prev = do +    go prev = do          (ss, cur) <- atomically $ do              ss <- mapM (sequence . fmap readTVar) statuses              blink <- terminalBlinkStatus tout @@ -132,4 +139,4 @@ displayStatusLine tout prefix1 prefix2 statuses = do          if all (maybe True jobStatusFinished) ss             then return () -           else go line cur +           else go cur |