Grails
  1. Grails
  2. GRAILS-8914

DirectoryWatcher and GrailsProjectWatcher in windows treat all GSP files as new after startup

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0 final, 2.0.1
    • Fix Version/s: 2.0.3, 2.1-RC1
    • Component/s: Build System
    • Labels:
      None

      Description

      All GSP files are treated as new files after startup in development mode and will stop reloading agent from finding real changes (only happening in windows environments). If there are 100 GSP files, the reloading agent finds the first "real" change after 500 seconds, which is a blocker on windows machines.

      On windows environment do:

      1. create-app testApp
      2. create-plugin testPlugin
      3. Add the plugin testPlugin to testApp by adding the following line the BuildConfig.groovy of testApp.

      grails.plugin.location.'testPlugin' = "../testPlugin"

      4. create-controller testController in testApp.
      5. change log level of

      org.codehaus.groovy.grails.compiler

      to INFO in testApp.
      6. start grails interactive from within testApp
      7. do "run-app"
      8. wait 10 seconds.
      9. after that error.gsp is treated as "new file"

      INFO compiler.GrailsProjectWatcher - File [C:\a\testPlugin\grails-app\views\error.gsp] added. Applying changes to application.

      (grails is doing that for ALL plugin-GSP files)

      10. if the plugin has 100 gsp files, this takes 100*5 seconds until any other change is taken, because he is busy "adding" existing GSPs to the project.

      This behaviour is only seen in windows environments. The same app starting in linux is NOT producing those "new file"-signal.

      The reason for this is in line 172 of DirectoryWatcher.java. In linux environments the same behaviour is happening: since all GSP files are not in the lastModifiedMap in the initialization phase (because, the "*" in extensions is added AFTER the view folders have been initialized) in linux they are added AFTER the application is started, however they are ignored because windows == false (see source code).

      So there is a bug here:

      • GSP files are not initializied in the lastModifiedMap. (this could only happen if the order of the PluginSourceFolders is different ...)

      I dont know why the extension array is maintained, since once "*" is added, every file will be observed.

        Issue Links

          Activity

          Christopher Rudolf created issue -
          Christopher Rudolf made changes -
          Field Original Value New Value
          Status Open [ 1 ] Edit [ 10000 ]
          Description
          I finally figured out, why the reloading agent is not coming into play on some windows machines and for bigger projects. Unfortunately I cannot build a simple small project to reproduce the problem, however here is the behaviour (which I hear a lot of grails users are struggeling with):

          1. Have a project with a lot of files.
          2. Use windows (only a windows issue! in linux everything is fine).
          3. Run the grails application (run-app)
          4. Do a change immediately to a groovy file.
          5. Change is compiled immediately.
          6. Do another change.
          7. Change is not taken.
          8. 10 minutes later: The change is taken.

          The reason for this is: After setting up the logging for the GrailsProjectWatcher class to info ('org.codehaus.groovy.grails.compiler'), the DirectoryWatcher sends a "new file"-message for ALL files part of some plugins:

          {code}
          grails> 2012-03-13 00:18:54,318 [Thread-14] INFO compiler.GrailsProjectWatcher - File [D:\projekte\zeitfest\git\zeitfest\zeitfest-email\grails-app\views\error.gsp] added. Applying changes
          to application.
          grails> 2012-03-13 00:18:59,366 [Thread-14] INFO compiler.GrailsProjectWatcher - File [D:\projekte\zeitfest\git\zeitfest\zeitfest-email\grails-app\views\officeMails\lostPassword.gsp] added
          . Applying changes to application.
          grails> 2012-03-13 00:19:04,413 [Thread-14] INFO compiler.GrailsProjectWatcher - File [D:\projekte\zeitfest\git\zeitfest\zeitfest-email\grails-app\views\officeMails\newKeeper.gsp] added. A
          pplying changes to application.
          ...
          {code}

          Although there are no changes at all! I looks like the DirectoryWatcher is confused by something and sends now a whole lot of "changes done" messages, which will stop the agent for another 5 seconds and finds the next change, etc. Look at the timestamps for the logging output.

          After something like 10 minutes all changes seemed to be found and the reloading agent works fine.

          It looks like that there are some racing conditions here.
          The reloading agent is not coming into play on windows machines and using bigger local plugins.

          Here is how to reproduce:
          1. create-app testApp
          2. create-plugin testPlugin
          3. Add the plugin testPlugin to testApp by adding the following line the BuildConfig.groovy of testApp.

          grails.plugin.location.'testPlugin' = "../testPlugin"

          4. create-controller testController in testApp.
          5. change log level of

          org.codehaus.groovy.grails.compiler

          to INFO in testApp.
          6. start grails interactive from within testApp
          7. do "run-app"
          8. wait 10 seconds.
          9. after that error.gsp is treated as "new file"

          INFO compiler.GrailsProjectWatcher - File [C:\a\testPlugin\grails-app\views\error.gsp] added. Applying changes to application.

          (grails is doing that for ALL plugin-GSP files)

          10. if the plugin has 100 gsp files, this takes 100*5 seconds until any other change is taken, because he is busy "adding" existing GSPs to the project.

          I.e. the DirectoryWatcher is confused by something at startup and sends now a whole lot of "new file" messages, which will stop the agent for another 5 seconds and finds the next change.

          This behaviour is only seen in windows environments. The same app starting in linux is NOT producing those "new file"-signal at all! It looks like, that it is a bug in the DirectoryWatcher or GrailsProjectWatcher.
          Hide
          Christopher Rudolf added a comment -

          Added a scenario on how to reproduce this bug.

          Show
          Christopher Rudolf added a comment - Added a scenario on how to reproduce this bug.
          Christopher Rudolf made changes -
          Status Edit [ 10000 ] Open [ 1 ]
          Christopher Rudolf made changes -
          Status Open [ 1 ] Edit [ 10000 ]
          Summary DirectoryWatcher and GrailsProjectWatcher racing conditions in windows DirectoryWatcher and GrailsProjectWatcher in windows treat all GSP files as new after startup
          Description The reloading agent is not coming into play on windows machines and using bigger local plugins.

          Here is how to reproduce:
          1. create-app testApp
          2. create-plugin testPlugin
          3. Add the plugin testPlugin to testApp by adding the following line the BuildConfig.groovy of testApp.

          grails.plugin.location.'testPlugin' = "../testPlugin"

          4. create-controller testController in testApp.
          5. change log level of

          org.codehaus.groovy.grails.compiler

          to INFO in testApp.
          6. start grails interactive from within testApp
          7. do "run-app"
          8. wait 10 seconds.
          9. after that error.gsp is treated as "new file"

          INFO compiler.GrailsProjectWatcher - File [C:\a\testPlugin\grails-app\views\error.gsp] added. Applying changes to application.

          (grails is doing that for ALL plugin-GSP files)

          10. if the plugin has 100 gsp files, this takes 100*5 seconds until any other change is taken, because he is busy "adding" existing GSPs to the project.

          I.e. the DirectoryWatcher is confused by something at startup and sends now a whole lot of "new file" messages, which will stop the agent for another 5 seconds and finds the next change.

          This behaviour is only seen in windows environments. The same app starting in linux is NOT producing those "new file"-signal at all! It looks like, that it is a bug in the DirectoryWatcher or GrailsProjectWatcher.
          All GSP files are treated as new files after startup in development mode and will stop reloading agent from finding real changes (only happening in windows environments). If there are 100 GSP files, the reloading agent finds the first "real" change after 500 seconds, which is a blocker on windows machines.

          On windows environment do:

          1. create-app testApp
          2. create-plugin testPlugin
          3. Add the plugin testPlugin to testApp by adding the following line the BuildConfig.groovy of testApp.

          grails.plugin.location.'testPlugin' = "../testPlugin"

          4. create-controller testController in testApp.
          5. change log level of

          org.codehaus.groovy.grails.compiler

          to INFO in testApp.
          6. start grails interactive from within testApp
          7. do "run-app"
          8. wait 10 seconds.
          9. after that error.gsp is treated as "new file"

          INFO compiler.GrailsProjectWatcher - File [C:\a\testPlugin\grails-app\views\error.gsp] added. Applying changes to application.

          (grails is doing that for ALL plugin-GSP files)

          10. if the plugin has 100 gsp files, this takes 100*5 seconds until any other change is taken, because he is busy "adding" existing GSPs to the project.

          This behaviour is only seen in windows environments. The same app starting in linux is NOT producing those "new file"-signal.

          The reason for this is in line 172 of DirectoryWatcher.java. In linux environments the same behaviour is happening: since all GSP files are not in the lastModifiedMap in the initialization phase (because, the "*" in extensions is added AFTER the view folders have been initialized) in linux they are added AFTER the application is started, however they are ignored because windows == false (see source code).

          So there is a bug here:
          - GSP files are not initializied in the lastModifiedMap. (this could only happen if the order of the PluginSourceFolders is different ...)

          I dont know why the extension array is maintained, since once "*" is added, every file will be observed.
          Christopher Rudolf made changes -
          Status Edit [ 10000 ] Open [ 1 ]
          Hide
          Christopher Rudolf added a comment -

          After removing the windows condition in the mentioned line and recompiling grails, reloading agent works perfectly fine. I guess it has to be removed. @Burt, why have you added this condition?

          Show
          Christopher Rudolf added a comment - After removing the windows condition in the mentioned line and recompiling grails, reloading agent works perfectly fine. I guess it has to be removed. @Burt, why have you added this condition?
          Show
          Christopher Rudolf added a comment - https://github.com/grails/grails-core/blob/master/grails-core/src/main/groovy/org/codehaus/groovy/grails/compiler/DirectoryWatcher.java#L172
          Lari Hotari made changes -
          Link This issue is related to GRAILS-8573 [ GRAILS-8573 ]
          Burt Beckwith made changes -
          Status Open [ 1 ] Closed [ 6 ]
          Assignee Burt Beckwith [ burtbeckwith ]
          Fix Version/s 2.0.3 [ 13094 ]
          Fix Version/s 2.1 [ 12801 ]
          Resolution Fixed [ 1 ]

            People

            • Assignee:
              Burt Beckwith
              Reporter:
              Christopher Rudolf
            • Votes:
              5 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development