-
Notifications
You must be signed in to change notification settings - Fork 82
Daemon App Domain #206
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
Daemon App Domain #206
Conversation
} | ||
|
||
Future<String> _restart(Map<String, dynamic> args) async { | ||
throw UnimplementedError(); |
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.
you could implement this as _callServiceExtension('hotRestart')
now if you wanted in this PR (that is ultimately probably what it should be)
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.
Gonna wait for a follow up PR as I'd like to add some tests.
webdev/test/daemon/utils.dart
Outdated
webdev.stdin.add(utf8.encode('[{"method":"daemon.shutdown","id":0}]\n')); | ||
// Try to shutdown webdev cleanly before killing it. | ||
await webdev.exitCode.timeout(const Duration(seconds: 5), onTimeout: () { | ||
webdev.kill(); |
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.
Hmm putting a timeout like this in the test seems like it will just hide actual issues. Presumably intellij etc won't be killing us like this.
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 suppose we can can listen for kill signals and try to gracefully close in webdev. The issue I'm trying to solve is that Chrome doesn't properly shutdown if webdev is killed. I can rework some stuff to see if there is a better pattern.
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.
No luck. I've experienced this in the past. If you kill the parent process of Chrome it will live on sometimes. This simply prevents random Chrome instances from staying open after doing a local test run. It should not have any impact on the tests.
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.
Presumably intellij etc won't be killing us like this.
FWIW, in VS Code we do something similar to this:
https://github.com/Dart-Code/Dart-Code/blob/master/src/debug/flutter_debug_impl.ts#L176-L177
https://github.com/Dart-Code/Dart-Code/blob/master/src/debug/dart_debug_impl.ts#L420-L423
To avoid having processes hang around, we:
- Send a message using the API to stop/detach
- Wait a seconds
- Call .kill() (which sends SIGTERM)
- Wait two seconds
- Call .kill(sigkill)
Calling SigKill is bad, because it won't let the process clean up any of its child processes, but sometimes sigterm either doesn't work quickly and we don't know if the process will terminate, so we have to gamble with a sigkill.
That said - I do also wonder if doing it here might mask issues (for example, if shutdown doesn't work at all, won't this just silently kill it after 5 seconds and it could go unnoticed?).
If you kill the parent process of Chrome it will live on sometimes.
I had a similar issue with flutter_tester (see flutter/flutter#20949 (comment)) and I was never able to find conclusive information on what the mechanism is for child processes terminating when their parent does (I couldn't find whether the child was supposed to notice the parent die and terminate, or whether the parent should terminate the child, or whether the OS should do it, etc.).
In Dart-Code, we now have "additionalPidsToTerminate" in some places, where we just collect up the PIDs we can and terminate them all.
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 would like to continue to push back on this - it seems as if sending the shutdown signal is not actually causing the daemon to shut down which isn't correct behavior.
If we are having issues actually shutting down webdev due to some streams being open or something then we should add a hard exit when we get the shutdown command, so that IDE's don't experience the same issue as the tests (and file an issue to diagnose the root cause).
If we want the test to clean itself up better after failures, then we could leave a timeout like this in but also throw an exception so the test will still fail and not silently kill webdev and succeed.
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.
Thanks for the details!
We used to do something similar in package:test
. Dartium was especially hard to kill. You could kill the main process of Dartium and its child processes would be promoted. Really weird. We ended up going with a hack where we would explicitly call kill on each child process of Dartium before killing the main process.
Normally when you hit ctrl+c
from WebDev the launched Chrome instance is also killed. However if you kill WebDev right after Chrome launches (as in these test cases) then for some reason Chrome isn't properly "attached" and lives on. All other child processes of WebDev are correctly cleaned up. I'm also extremely confident that the build daemon is properly shutdown as I spent weeks ensuring that was the case. We also have tests for it as well.
Finally, I'm confident that WebDev properly shutsdown with the daemon exit command as we have a test for this functionality in daemon_domain_test.dart
. It does not exercise this exitWebDev
code path.
webdev/lib/src/daemon/daemon.dart
Outdated
@@ -19,10 +19,10 @@ class Daemon { | |||
Daemon( | |||
Stream<Map<String, dynamic>> commandStream, | |||
this._sendCommand, | |||
Future<ServeController> futureServeController, | |||
Future<ServerManager> futureServerManagers, |
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.
futureServerManager
chrome.chromeConnection, | ||
Future<DebugService> startDebugService( | ||
ChromeConnection chromeConnection, String appUrl) async { | ||
return await DebugService.start( |
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.
nit: you don't need the await here
webdev/test/daemon/utils.dart
Outdated
webdev.stdin.add(utf8.encode('[{"method":"daemon.shutdown","id":0}]\n')); | ||
// Try to shutdown webdev cleanly before killing it. | ||
await webdev.exitCode.timeout(const Duration(seconds: 5), onTimeout: () { | ||
webdev.kill(); |
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 would like to continue to push back on this - it seems as if sending the shutdown signal is not actually causing the daemon to shut down which isn't correct behavior.
If we are having issues actually shutting down webdev due to some streams being open or something then we should add a hard exit when we get the shutdown command, so that IDE's don't experience the same issue as the tests (and file an issue to diagnose the root cause).
If we want the test to clean itself up better after failures, then we could leave a timeout like this in but also throw an exception so the test will still fail and not silently kill webdev and succeed.
With regards to #206 (comment) see my discussion here #206 (comment). We do have a test that the WebDev process is properly killed and it does not exercise the |
SSE
v 2.0.0 as it fixes an issue with multiple listeners on the connection streamclient.js
DevWorkflow
abstractionserve
anddaemon
command to make use ofDevWorkflow
AppDomain
for thedaemon
commandServerManager
_WebdevClient
out ofDevHandler
and intoWebdevVmClient
AppDomain
.DevHandler
so that we can easily create aDebugService
daemon
command