docker: When running as effective init inside container, wait on zombies.

This commit is contained in:
Joey Hess 2014-04-04 18:21:54 -04:00
parent 160b598756
commit 17d46c67fa
3 changed files with 16 additions and 6 deletions

View File

@ -17,6 +17,7 @@ import Utility.Path
import Control.Concurrent.Async import Control.Concurrent.Async
import System.Posix.Directory import System.Posix.Directory
import System.Posix.Process
import Data.List import Data.List
-- | Configures docker with an authentication file, so that images can be -- | Configures docker with an authentication file, so that images can be
@ -272,6 +273,9 @@ runningContainer cid@(ContainerId hn cn) image containerprops = containerDesc ci
-- | Called when propellor is running inside a docker container. -- | Called when propellor is running inside a docker container.
-- The string should be the container's ContainerId. -- The string should be the container's ContainerId.
-- --
-- This process is effectively init inside the container.
-- It even needs to wait on zombie processes!
--
-- Fork a thread to run the SimpleSh server in the background. -- Fork a thread to run the SimpleSh server in the background.
-- In the foreground, run an interactive bash (or sh) shell, -- In the foreground, run an interactive bash (or sh) shell,
-- so that the user can interact with it when attached to the container. -- so that the user can interact with it when attached to the container.
@ -291,19 +295,23 @@ chain s = case toContainerId s of
Just cid -> do Just cid -> do
changeWorkingDirectory localdir changeWorkingDirectory localdir
writeFile propellorIdent . show =<< readIdentFile cid writeFile propellorIdent . show =<< readIdentFile cid
gogo reapzombies
-- Run boot provisioning before starting simpleSh, -- Run boot provisioning before starting simpleSh,
-- to avoid ever provisioning twice at the same time. -- to avoid ever provisioning twice at the same time.
whenM (checkProvisionedFlag cid) $ do whenM (checkProvisionedFlag cid) $ do
let shim = Shim.file (localdir </> "propellor") (localdir </> shimdir cid) let shim = Shim.file (localdir </> "propellor") (localdir </> shimdir cid)
unlessM (boolSystem shim [Param "--continue", Param $ show $ Chain $ fromContainerId cid]) $ unlessM (boolSystem shim [Param "--continue", Param $ show $ Chain $ fromContainerId cid]) $
warningMessage "Boot provision failed!" warningMessage "Boot provision failed!"
void $ async $ simpleSh $ namedPipe cid gogo $ simpleSh $ namedPipe cid
forever $ do forever $ do
void $ ifM (inPath "bash") void $ ifM (inPath "bash")
( boolSystem "bash" [Param "-l"] ( boolSystem "bash" [Param "-l"]
, boolSystem "/bin/sh" [] , boolSystem "/bin/sh" []
) )
putStrLn "Container is still running. Press ^P^Q to detach." putStrLn "Container is still running. Press ^P^Q to detach."
where
gogo = void . async . forever . void . tryIO
reapzombies = void $ getAnyProcessStatus True False
-- | Once a container is running, propellor can be run inside -- | Once a container is running, propellor can be run inside
-- it to provision it. -- it to provision it.
@ -335,7 +343,7 @@ provisionContainer cid = containerDesc cid $ Property "provision" $ do
hPutStrLn stderr s hPutStrLn stderr s
hFlush stderr hFlush stderr
go Nothing rest go Nothing rest
Done _ -> ret lastline Done -> ret lastline
go lastline [] = ret lastline go lastline [] = ret lastline
ret lastline = return $ fromMaybe FailedChange $ ret lastline = return $ fromMaybe FailedChange $

View File

@ -9,7 +9,6 @@ import Network.Socket
import Control.Concurrent.Chan import Control.Concurrent.Chan
import Control.Concurrent.Async import Control.Concurrent.Async
import System.Process (std_in, std_out, std_err) import System.Process (std_in, std_out, std_err)
import System.Exit
import Propellor import Propellor
import Utility.FileMode import Utility.FileMode
@ -18,7 +17,7 @@ import Utility.ThreadScheduler
data Cmd = Cmd String [String] data Cmd = Cmd String [String]
deriving (Read, Show) deriving (Read, Show)
data Resp = StdoutLine String | StderrLine String | Done ExitCode data Resp = StdoutLine String | StderrLine String | Done
deriving (Read, Show) deriving (Read, Show)
simpleSh :: FilePath -> IO () simpleSh :: FilePath -> IO ()
@ -49,7 +48,7 @@ simpleSh namedpipe = do
v <- readChan chan v <- readChan chan
hPutStrLn h (show v) hPutStrLn h (show v)
case v of case v of
Done _ -> noop Done -> noop
_ -> runwriter _ -> runwriter
writer <- async runwriter writer <- async runwriter
@ -59,7 +58,9 @@ simpleSh namedpipe = do
(mkreader StdoutLine outh) (mkreader StdoutLine outh)
(mkreader StderrLine errh) (mkreader StderrLine errh)
writeChan chan . Done =<< waitForProcess pid void $ tryIO $ waitForProcess pid
writeChan chan Done
wait writer wait writer

1
debian/changelog vendored
View File

@ -3,6 +3,7 @@ propellor (0.2.3) UNRELEASED; urgency=medium
* docker: Fix laziness bug that caused running containers to be * docker: Fix laziness bug that caused running containers to be
unnecessarily stopped and committed. unnecessarily stopped and committed.
* Add locking so only one propellor can run at a time on a host. * Add locking so only one propellor can run at a time on a host.
* docker: When running as effective init inside container, wait on zombies.
-- Joey Hess <joeyh@debian.org> Fri, 04 Apr 2014 15:58:03 -0400 -- Joey Hess <joeyh@debian.org> Fri, 04 Apr 2014 15:58:03 -0400