Open zouabimourad opened 6 years ago
Same thing when i stop gwt compilation .. the leaf java process ( gwt compiler process ) is still running ...
I've been a Linux user for years and I don't have any expertise on Windows idiosyncrasies.
Patches welcome!
I have the same problem with the 1.8.2 version of the legacy plugin but the 1.8.1 is ok
I will try to fix it.
It might be due to an update of the plexus-utils dependency (from 3.0.16 to 3.1.0 between org.codehaus.mojo:gwt-maven-plugin 2.8.1 and 2.8.2; and from 3.0.21 to 3.1.0 in net.ltgt.gwt.maven:gwt-maven-plugin 1.0-rc-9 compared to previous versions). You should be able to test with earlier versions of plexus-utils by declaring them in the plugin's dependencies:
<plugin>
<groupId>net.ltgt.gwt.maven</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>1.0-rc-9</version>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.16</version>
</dependency>
</dependencies>
</plugin>
If that fixes it for you, then we'd have at least a lead to explore and possibly report it to plexus-utils (if that doesn't fix it though, it might be that the dependency is not taken into account; run Maven with -X
–debug logs– and look for the plugin's class world/realm to see what's actually used)
It works fine with the dependency override. There is no a cmd
process between maven's JVM and Codeserver's JVM anymore .. and after Exit all the JMVs are Stopped. Thx !
Let's keep it open please. You have a workaround, but this still needs fixing (even if that only means waiting for a new version of plexus-utils with a fix and upgrading to it; or temporarily downgrading)
Easiest solution would be to use jetty's stopPort if possible.
If that's not possible, a cross-platform library to kill processes by port number would be in order. (win10/linux: netstat, win10: tasklist+taskkill, linux; kill)
Here is a quick and dirty solution I used in one of my projects:
But it is mixed with Linux where I simply put an environment variable into the started process and then identify the process using that unique tag. That's not possible under Windows it seems.
However, I should note that GWT dev mode does not work too well under Windows anyways because it seems that it sometimes has a race condition where the strict file locking on Windows produces a file access conflict with itself.
Maybe it's possible to NOT FORK the codeserver and run it inside the main maven process, at least when using the @default-cli execution? Or attach the forked process' resources to the parent process such that a termination of the parent leads to the termination of the child somehow?
Adding
<plugin>
<groupId>net.ltgt.gwt.maven</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<configuration>
<systemProperties>
<STOP.PORT>9999</STOP.PORT>
<STOP.KEY>GWTCODESERVER</STOP.KEY>
</systemProperties>
</configuration>
</plugin>
allows to shut down a stray codeserver by sending the key to the stop port:
java -jar ./jetty-distribution-9.4.14.v20181114/start.jar -DSTOP.PORT=9999 -DSTOP.KEY=GWTCODEGSERVER--stop
So I recommend setting the stop port by default with a default key value and checking the port connectivity before trying to start the codeserver.
Also, on Windows the codeserver is likely to keep locking files in target/ when using CTRL-C. Not sure how to go about this. Probably, there should be a gwt:stop command that is tied to the pre-clean phase by default.
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4717969
a shutdown hook would at least solve the CTRL-C issue on Windows:
final ProcessBuilder pb =
new ProcessBuilder("java", "ControlCProblemDemo");
final Process p = pb.start();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("killing it");
p.destroyForcibly();
}
}));
There is such a shutdown hook already, with the exception that it calls destroy()
rather than destroyForcibly()
(plexus-utils is likely to have/want to support old JVMs though, and destroyForcibly()
w as added in 1.8).
https://github.com/codehaus-plexus/plexus-utils/blob/plexus-utils-3.1.1/src/main/java/org/codehaus/plexus/util/cli/CommandLineUtils.java#L134-L152
That being said, on Windows, destroyForcibly()
just calls destroy()
:
https://github.com/unofficial-openjdk/openjdk/blob/2357b5fc925a96e53e6e9a84230be327424ad1ce/src/java.base/windows/classes/java/lang/ProcessImpl.java#L553-L557
IOW, what you're proposing is already there.
On Windows, a workaround might be to use gwt:devmode
with <devmodeArg>-noserver</devmodeArg>
; that way you can easily stop the code server by closing the devmode window.
okay, I didn't see that the shutdown hook was already used because the forked plexus-utils repo has a non-working search function. pft.
Apart from that, I played around with plexus-utils to find out why my own test case works, but plexus-utils doesn't. Answer: it seems to be related to the stream pumpers. When I replace Runtime.exec() with ProcessBuilder and use its inheritIO() instead, the child process goes away as expected. Specifically using Redirect.INHERIT on the child's STDIN fixes the issue - maybe the child's STDIN FD doesn't get closed the way it's currently handled.
Commandline:
/**
* Executes the command.
*/
public Process execute()
throws CommandLineException
{
// TODO: Provided only for backward compat. with <= 1.4
verifyShellState();
Process process;
// addEnvironment( "MAVEN_TEST_ENVAR", "MAVEN_TEST_ENVAR_VALUE" );
String[] environment = getEnvironmentVariables();
File workingDir = shell.getWorkingDirectory();
ProcessBuilder pb = new ProcessBuilder(getCommandline());
pb.directory(workingDir);
pb.inheritIO();
if (environment != null) {
for (String s : environment) {
String[] kv = s.split("=", 2);
pb.environment().put(kv[0], kv[1]);
}
}
try
{
if ( workingDir != null ) {
if ( !workingDir.exists() )
{
throw new CommandLineException( "Working directory \"" + workingDir.getPath()
+ "\" does not exist!" );
}
else if ( !workingDir.isDirectory() )
{
throw new CommandLineException( "Path \"" + workingDir.getPath()
+ "\" does not specify a directory." );
}
}
process = pb.start();
}
catch ( IOException ex )
{
throw new CommandLineException( "Error while executing process.", ex );
}
return process;
}
the build failure is not because of my changes btw
Update on this issue, because the workaround above no longer works as-is with version 1.0.1 (similar workarounds might work, downgrading both plexus-utils and plexus-io, possibly more dependencies): the bug is upstream in plexus-utils, which is used in many Maven plugins (including Surefire and the maven-compiler-plugin ‼), this is where it needs to be fixed.
I'll keep this issue open because indeed it's an issue with the plugin, but I'll only accept PRs that update plexus-utils to a version that fixes the bug.
In the mean time, don't use Ctrl+C or similar (killing the Maven task in Eclipse), and rather kill the GWT process itself directly. You could also probably use gwt:dev
(with -noserver
) instead of gwt:codeserver
, as it will give you a Swing window that you can close to stop GWT.
You could also probably use
gwt:dev
Do you mean gwt:devmode
?
Oops, yes, gwt:devmode
indeed.
Oops, yes,
gwt:devmode
indeed.
and without -noserver
with noserver
: devmode is then equivalent to codeserver, just with an additional swing window.
So, if you've created a client/server/shared architect, then instead of mvn gwt:codeserver -pl *-client -am
, you'd do:
mvn gwt:devmode -pl *-client -am -Dnoserver
Works great, thanks! 👍
@tbroyer in case GWT remove the DevMode (as mentioned here: (https://www.gwtproject.org/release-notes.html#Release_Notes_2_11_0), will this have an impact on the work around?
For the time being, the goal seems to be to eventually default to -noserver
(https://github.com/gwtproject/gwt/issues/9863) (and then maybe remove the JettyLauncher
in favor of the newly added StaticResourcesServer
, that's at least what I would do if you ask me), but not to remove DevMode entirely.
Yes, that makes sense. So, the workaround will also work in the future. I was unsure, if it might fail in the future and a new workaround is needed. Thanks.
So, if you've created a client/server/shared architect, then instead of
mvn gwt:codeserver -pl *-client -am
, you'd do:mvn gwt:devmode -pl *-client -am -Dnoserver
Works great, thanks! 👍
Note: After a mvn clean
the devmode solution will break. The browser won't be able to find the nocache.js file.
Running the mvn gwt:codeserver -pl *-client -am
once (and then manually killing it), the devmode solution will start working again. I'm not entirely sure why, I suspect it's something to do with the target/gwt/codeserver directory it creates.
Did you configure warDir
to the same value as codeserver's launcherDir
? If not, then devmode won't generate the nocache.js where you expect them, that's why you'd need to run codeserver to generate them first.
Ah, thank you @tbroyer . Yes, that was the issue. Now with:
<plugin>
<groupId>net.ltgt.gwt.maven</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<inherited>false</inherited>
<configuration>
<launcherDir>${basedir}/mywebapp-server/target/classes/launcherDir/</launcherDir>
<warDir>${basedir}/mywebapp-server/target/classes/launcherDir/</warDir>
</configuration>
</plugin>
And now it still works great after a mvn clean
.
Fwiw, I just published version 2024.2.11 of the gwt-maven-archetypes that adds the warDir
configuration, and a note in the README explaining when one may want to use devmode, and linking here.
It also adds the -noserver
argument.
Hi,
When i launch
mvn gwt:codesever
3 process are started ( maven jvm , cmd and codesever jvm )When I Stop mvn .. the 2 first process are stopped but the codeserver jvm is still running
Regards.