Skip to content
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

Code Server's Process Still Running After Stopping the maven launcher ( CTRL + C ) #110

Open
zouabimourad opened this issue Apr 10, 2018 · 26 comments

Comments

@zouabimourad
Copy link

zouabimourad commented Apr 10, 2018

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.

@zouabimourad
Copy link
Author

Same thing when i stop gwt compilation .. the leaf java process ( gwt compiler process ) is still running ...

@tbroyer
Copy link
Owner

tbroyer commented May 16, 2018

I've been a Linux user for years and I don't have any expertise on Windows idiosyncrasies.

Patches welcome!

@tbroyer tbroyer added the help wanted Extra attention is needed label May 16, 2018
@zouabimourad
Copy link
Author

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.

@tbroyer
Copy link
Owner

tbroyer commented May 16, 2018

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)

@zouabimourad
Copy link
Author

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 !

@tbroyer
Copy link
Owner

tbroyer commented May 18, 2018

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)

@jjYBdx4IL
Copy link

jjYBdx4IL commented Jan 29, 2019

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:

https://github.com/jjYBdx4IL/example-maven-project-setups/blob/master/gwt-example/devel-it/src/main/resources/startStop.sh

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?

@jjYBdx4IL
Copy link

jjYBdx4IL commented Jan 30, 2019

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.

@jjYBdx4IL
Copy link

jjYBdx4IL commented Jan 31, 2019

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();
            }
        }));

@tbroyer
Copy link
Owner

tbroyer commented Jan 31, 2019

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.

@jjYBdx4IL
Copy link

jjYBdx4IL commented Jan 31, 2019

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;
}

@jjYBdx4IL
Copy link

Patch: #125

@jjYBdx4IL
Copy link

the build failure is not because of my changes btw

@tbroyer
Copy link
Owner

tbroyer commented Apr 26, 2022

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.

@tbroyer tbroyer removed the help wanted Extra attention is needed label Apr 29, 2022
@ratuka
Copy link

ratuka commented Oct 27, 2022

You could also probably use gwt:dev

Do you mean gwt:devmode?

@tbroyer
Copy link
Owner

tbroyer commented Oct 27, 2022

Oops, yes, gwt:devmode indeed.

@ratuka
Copy link

ratuka commented Oct 27, 2022

Oops, yes, gwt:devmode indeed.

and without -noserver

@tbroyer
Copy link
Owner

tbroyer commented Oct 27, 2022

with noserver: devmode is then equivalent to codeserver, just with an additional swing window.

@craigmit
Copy link

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! 👍

@FrankHossfeld
Copy link

FrankHossfeld commented Jan 29, 2024

@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?

@tbroyer
Copy link
Owner

tbroyer commented Jan 29, 2024

For the time being, the goal seems to be to eventually default to -noserver (gwtproject/gwt#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.

@FrankHossfeld
Copy link

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.

@craigmit
Copy link

craigmit commented Feb 10, 2024

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.

@tbroyer
Copy link
Owner

tbroyer commented Feb 10, 2024

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.

@craigmit
Copy link

craigmit commented Feb 10, 2024

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.

@tbroyer
Copy link
Owner

tbroyer commented Feb 11, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants