-
Notifications
You must be signed in to change notification settings - Fork 721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cross-platform clean shutdown mechanism #767
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Once this is merged I will change cardano-wallet to also use a FD other than stdin.
I think it needs changes to work on Windows though.
@@ -249,6 +252,15 @@ parseValidateDB = | |||
<> help "Validate all on-disk database files" | |||
) | |||
|
|||
parseShutdownIPC :: Parser (Maybe Fd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this will compile on Windows because it's HANDLE
there. Perhaps use Int
here and sort out the rest when it's time to use fdToHandle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GHC uses the MS C lib on Windows which does actually handle these Fds.
where | ||
waitForEOF :: IO () | ||
waitForEOF = do | ||
hnd <- IO.fdToHandle fd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need some CPP for Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Surprisingly this is not Unix specific code.
| otherwise -> throwIO e | ||
|
||
Right _ -> | ||
throwIO $ IO.userError "--shutdown-ipc FD does not expect input" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. Reporting an error in this case is probably more sensible than consuming the input.
cardano-node/src/Cardano/Node/Run.hs
Outdated
withShutdownHandler :: NodeProtocolMode -> Tracer IO String -> IO () -> IO () | ||
withShutdownHandler (RealProtocolMode NodeCLI{shutdownIPC = Just (Fd fd)}) | ||
tracer action = | ||
race_ waitForEOF action |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this need application of the forkIO/MVar hack to avoid deadlocking on Windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes you're right. Sigh. Because this uses cancel
on the left action when the right one finishes, and that will never complete...
ca9fef4
to
8fe713d
Compare
Otherwise every time we add/remove/change fields in these records then a dozen places in the code need updating. Also add a TODO about the structure of these types. They now share nothing but this is really too extreme, as demonstrated by the places that this patch touches. There are a lot of places where we extract the same information for both mock and real modes. So we should share the things that are always the same.
Fixes #726 On Windows there is no standard reliable mechanism to politely ask a process to stop. There is only the brutal TerminateProcess. Using that by default is not great since it means the node always has to revalidate its chain DB on startup. This adds an ad-hoc mechainsim that Daedalus can use to reliably shut down the node process. The --shutdown-ipc flag takes the FD of the read ebd of an inherited pipe. If provided, the node will monitor that pipe when when the write end of the pipe is closed then the node will initiate a clean shutdown. So Daedalus can explicitly terminate the node by closing the write end of the pipe. If Daedalus terminates uncleanly then the pipe will also be closed and the node will also shut down. Although this mechanism is needed for Windows, it is also cross-platform so it can be used by Daedalus across all platforms.
8fe713d
to
45d2a06
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great 👍
-- process itself terminated, then we initiate a clean shutdown. | ||
-- | ||
withShutdownHandler :: NodeProtocolMode -> Tracer IO String -> IO () -> IO () | ||
withShutdownHandler (RealProtocolMode NodeCLI{shutdownIPC = Just (Fd fd)}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
-> Consensus.TopLevelConfig blk | ||
-> IO () | ||
createTracers npm' tr tracer cfg = do | ||
case npm' of | ||
RealProtocolMode (NodeCLI _ rNodeAddr _ runDBValidation) -> do | ||
RealProtocolMode NodeCLI{nodeAddr, validateDB} -> do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So NamedFieldPuns
are good to go, unlike what was being categorically told by people.
And yes, personally, they make complete sense here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. NamedFieldPuns
are great. RecordWildcards
is what makes some people grumpy.
I've ran some tests on the Furthermore, integration tests are passing for non-brutal shutdowns working correctly. |
bors merge |
Build succeeded |
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
This modifies the clean shutdown handler to use a FD from the command line, rather than taking stdin. It also makes the logic even simpler, as shown in IntersectMBO/cardano-node#767 The command-line arguments are changed from --shutdown-handler to --shutdown-ipc FD so that they are identical to cardano-node.
Cross-platform clean shutdown support with
--shutdown-ipc FD
flagFixes #726
On Windows there is no standard reliable mechanism to politely ask a process to stop. There is only the brutal TerminateProcess. Using that by default is not great since it means the node always has to revalidate its chain DB on startup.
This adds an ad-hoc mechainsim that Daedalus can use to reliably shut down the node process. The
--shutdown-ipc
flag takes the FD of the read end of an inherited pipe. If provided, the node will monitor that pipe when when the write end of the pipe is closed then the node will initiate a clean shutdown. So Daedalus can explicitly terminate the node by closing the write end of the pipe. If Daedalus terminates uncleanly then the pipe will also be closed and the node will also shut down.Although this mechanism is needed for Windows, it is also cross-platform so it can be used by Daedalus across all platforms.