[GRADLE-1073] Gradle daemon should gracefully handle version changes Created: 28/Jul/10  Updated: 04/Jan/13  Resolved: 24/Nov/10

Status: Resolved
Project: Gradle
Affects Version/s: 0.9.1
Fix Version/s: 0.9-rc-3

Type: Improvement
Reporter: Chris Beams Assignee: Adam Murdoch
Resolution: Fixed Votes: 0


 Description   

Repro steps:

  1. stop any running gradle daemon
  2. install 0.9-20100726131918+0200 via the gradle wrapper
  3. gradle clean
  4. notice the gradle daemon start
  5. leave the daemon running
  6. install 0.9-20100728180850+0200 via the gradle wrapper
  7. gradle clean
  8. notice the following serialization issues
    java.io.InvalidClassException: org.gradle.launcher.GradleDaemon$BuildArgs; local class incompatible: 
    stream classdesc serialVersionUID = -9202617733128175087, local class serialVersionUID = 4032985459256264336
            at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
            at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1583)
            at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
            at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
            at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
            at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
            at org.gradle.launcher.GradleDaemon.run(GradleDaemon.java:46)
            at org.gradle.launcher.GradleDaemon.main(GradleDaemon.java:29)
    

It appears that the gradle process does a blind check for a running daemon and if it's up, attempts to communicate with it. Better would be issuing a version check first, shutting down and restarting the daemon if versions are incompatible.

A minor issue perhaps, but goal number one with the daemon is to make it invisible.

Another use case for this would be not an upgrade of gradle, but simply moving between different gradle-built projects that are using different versions in the wrapper. In this case, it might be best to start a second daemon on its own dedicated port. It's a bit of an edge case, but if a user is toggling between two projects and issuing builds, they'll continually incur the daemon startup overhead. Shouldn't be a problem to just spin up a new daemon, but this does create the possibility of stale daemons lying around after a legitimate upgrade occurs.



 Comments   
Comment by Chris Beams [ 09/Sep/10 ]

Another stack trace just gotten when upgrading to 0.9-build-daemon-20100909161815+1000:

cbeams@anakata:~/Work/spring-amqp/spring-amqp[gradle]>$ ./gradlew -t
Downloading http://gradle.artifactoryonline.com/gradle/distributions/gradle-snapshots/gradle-0.9-build-daemon-20100909161815+1000-bin.zip
...
Unzipping /Users/cbeams/.gradle/wrapper/dists/gradle-0.9-build-daemon-20100909161815+1000-bin.zip to /Users/cbeams/.gradle/wrapper/dists
Set executable permissions for: /Users/cbeams/.gradle/wrapper/dists/gradle-0.9-build-daemon-20100909161815+1000/bin/gradle
org.gradle.util.UncheckedException: java.io.StreamCorruptedException: invalid stream header: 6A617661
        at org.gradle.util.UncheckedException.asUncheckedException(UncheckedException.java:31)
        at org.gradle.launcher.GradleDaemon.clientMain(GradleDaemon.java:107)
        at org.gradle.launcher.Main.execute(Main.java:82)
        at org.gradle.launcher.Main.main(Main.java:40)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:49)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:38)
        at org.gradle.wrapper.Wrapper.execute(Wrapper.java:58)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:42)
Caused by: java.io.StreamCorruptedException: invalid stream header: 6A617661
        at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:783)
        at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)
        at org.gradle.util.ClassLoaderObjectInputStream.<init>(ClassLoaderObjectInputStream.java:27)
        at org.gradle.messaging.remote.internal.Message$ExceptionReplacingObjectInputStream.<init>(Message.java:151)
        at org.gradle.messaging.remote.internal.Message.receive(Message.java:37)
        at org.gradle.launcher.GradleDaemon.run(GradleDaemon.java:156)
        at org.gradle.launcher.GradleDaemon.clientMain(GradleDaemon.java:105)
        ... 14 more

This would persist with all subsequent ./gradlew -t invocations, but was solved by kill -9 <GRADLE_DAEMON_PID> and retrying ./gradlew -t

Comment by Chris Beams [ 27/Oct/10 ]

As an update, I just upgraded from the gradle_daemon branch from Oct 25th. I had the daemon running in the background on that version, then upgraded to 0.9-build-daemon-20101027111821+1100. Upon trying to run a gradle command after upgrading, gradle simply exited silently – no stack trace, and nothing even when passing in -d.

Upon running ./gradlew --stop, the old daemon shut down as expected and the new version started up on the next invocation.

At any rate, that experience would have been pretty tough to deal with for someone unfamiliar with the details of the daemon. And while it's not likely a normal build operator would be doing such an upgrade on a regular basis, it may be relatively frequent for our developers as we keep up to date with daemon updates and fixes over the next few weeks.

Generated at Wed Jun 30 11:46:12 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.