Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.7.4, 3.8
    • Component/s: Core
    • Labels:
      None
    • Number of attachments :
      1

      Description

      I'm running an embedder as part of another java application. When the execution of the embedder completes I can see files on disk but they are empty (or of small size) and the files are locked open by the process (can't delete them on windows). It appears that the files are only written out when I exit the java process in which the embedder has been started.

        Activity

        Hide
        Mauro Talevi added a comment -

        Do you have a sample project that reproduces the issue?

        Show
        Mauro Talevi added a comment - Do you have a sample project that reproduces the issue?
        Hide
        Alexander Lehmann added a comment - - edited

        I think I noticed this a while back as well, but I didn't get around to actually checking out why this happens. I have created a sample project that shows the problem, however this is only noticeable in Windows since open files cannot be deleted in Windows, but this is possible in Linux (if your directory is on nfs you may get leftover nfs files for the open delete files).

        Show
        Alexander Lehmann added a comment - - edited I think I noticed this a while back as well, but I didn't get around to actually checking out why this happens. I have created a sample project that shows the problem, however this is only noticeable in Windows since open files cannot be deleted in Windows, but this is possible in Linux (if your directory is on nfs you may get leftover nfs files for the open delete files).
        Alexander Lehmann made changes -
        Field Original Value New Value
        Attachment fileclose.zip [ 61913 ]
        Hide
        Alexander Lehmann added a comment -

        this is basically a project created with the simple archetype plus a main class that calls the run method and waits.
        If you run the test and then try to delete the files in the target/jbehave in Windows, the java process has the files locked and they are only released when the jvm exits.
        It may be possible to observe the open files with lsof in Linux, I haven't tried that since I not have a Linux machine available right now.

        Show
        Alexander Lehmann added a comment - this is basically a project created with the simple archetype plus a main class that calls the run method and waits. If you run the test and then try to delete the files in the target/jbehave in Windows, the java process has the files locked and they are only released when the jvm exits. It may be possible to observe the open files with lsof in Linux, I haven't tried that since I not have a Linux machine available right now.
        Hide
        Pascal Rapicault added a comment -

        Thanks for attaching the sample Alexander.

        Show
        Pascal Rapicault added a comment - Thanks for attaching the sample Alexander.
        Hide
        Alexander Lehmann added a comment -

        haven't had time to look at the actual problem though

        Show
        Alexander Lehmann added a comment - haven't had time to look at the actual problem though
        Hide
        Alexander Lehmann added a comment -

        I guess PrintStreamOutput needs a close() method that closes the PrintStream that is called when a report is finished.
        Or the StoryReporter interface needs a finish or close method that is called to close the Stream if there is one.

        Show
        Alexander Lehmann added a comment - I guess PrintStreamOutput needs a close() method that closes the PrintStream that is called when a report is finished. Or the StoryReporter interface needs a finish or close method that is called to close the Stream if there is one.
        Hide
        Alexander Lehmann added a comment -

        Does anybody have an idea how to generically check for open files?

        I guess it would be possible in this case to create a subclass of FilePrintStreamFactory that gives out a PrintStream that can be checked if it was closed, but I wonder how this could be solved in general.

        Show
        Alexander Lehmann added a comment - Does anybody have an idea how to generically check for open files? I guess it would be possible in this case to create a subclass of FilePrintStreamFactory that gives out a PrintStream that can be checked if it was closed, but I wonder how this could be solved in general.
        Hide
        Pascal Rapicault added a comment -

        If I wanted to look into this, where would I start? I mean where are the files that are being written actually opened?

        Show
        Pascal Rapicault added a comment - If I wanted to look into this, where would I start? I mean where are the files that are being written actually opened?
        Hide
        Alexander Lehmann added a comment -

        The report files are created by FilePrintStreamFactory.createPrintStream(), which is called when the respective Format is processed in StoryReporterBuilder
        the main problem is finding the point where the PrintStream could be closed and then finding the PrintStreams that should actually be closed.
        I started trying to implement a close() method for each StoryReporter that takes care of closing the PrintStream and passing the close call to the delegate reporter etc. This does not yet work correctly, until now I can close the Before and After report files.

        However the report files are still open, so they are apparently opened later in the code again and these streams are not closed either (i.e. each open file is leaked more than once). I haven't found out where this happens yet.

        Show
        Alexander Lehmann added a comment - The report files are created by FilePrintStreamFactory.createPrintStream(), which is called when the respective Format is processed in StoryReporterBuilder the main problem is finding the point where the PrintStream could be closed and then finding the PrintStreams that should actually be closed. I started trying to implement a close() method for each StoryReporter that takes care of closing the PrintStream and passing the close call to the delegate reporter etc. This does not yet work correctly, until now I can close the Before and After report files. However the report files are still open, so they are apparently opened later in the code again and these streams are not closed either (i.e. each open file is leaked more than once). I haven't found out where this happens yet.
        Hide
        Mauro Talevi added a comment -

        They should be closed in the afterStory(boolean givenStory) method of the PrintStreamOuput.

        Have a look at the TemplateableOutput - it does something similar.

        Show
        Mauro Talevi added a comment - They should be closed in the afterStory(boolean givenStory) method of the PrintStreamOuput. Have a look at the TemplateableOutput - it does something similar.
        Hide
        Alexander Lehmann added a comment -

        thanks, that takes care of a few open files, but there are still some leaks.
        I will look a bit further.

        Show
        Alexander Lehmann added a comment - thanks, that takes care of a few open files, but there are still some leaks. I will look a bit further.
        Hide
        Alexander Lehmann added a comment -

        Fixed JBEHAVE-848: Report files not closed

        added close() calls to afterStory in PrintStreamOutput and to a few Writers that were not closed.
        And changed a few calls that where constructing streams as a parameter to IOUtils.toString.

        https://github.com/alexlehm/jbehave-core/commit/31000d962e0382bca6dddfebe8b7ccb2fb5009ba

        Show
        Alexander Lehmann added a comment - Fixed JBEHAVE-848 : Report files not closed added close() calls to afterStory in PrintStreamOutput and to a few Writers that were not closed. And changed a few calls that where constructing streams as a parameter to IOUtils.toString. https://github.com/alexlehm/jbehave-core/commit/31000d962e0382bca6dddfebe8b7ccb2fb5009ba
        Hide
        Alexander Lehmann added a comment - - edited

        I should add that of course I'm not sure if I caught all files, however I checked that test program doesn't have files open.

        The changes do not contain any unit tests since I am still not sure how to test this, maybe I can add some later.

        Show
        Alexander Lehmann added a comment - - edited I should add that of course I'm not sure if I caught all files, however I checked that test program doesn't have files open. The changes do not contain any unit tests since I am still not sure how to test this, maybe I can add some later.
        Mauro Talevi made changes -
        Fix Version/s 3.7.4 [ 18964 ]
        Hide
        Mauro Talevi added a comment -

        Patch pulled. Added a custom IOUtils class for JBehave to collect methods with close option.

        Pushed new 3.8-SNAPSHOT release.

        Pascal, can you please test snapshot? If working we'll cut the 3.7.4 release.

        Show
        Mauro Talevi added a comment - Patch pulled. Added a custom IOUtils class for JBehave to collect methods with close option. Pushed new 3.8-SNAPSHOT release. Pascal, can you please test snapshot? If working we'll cut the 3.7.4 release.
        Mauro Talevi made changes -
        Assignee Mauro Talevi [ maurotalevi ]
        Mauro Talevi made changes -
        Status Open [ 1 ] In Progress [ 3 ]
        Hide
        Alexander Lehmann added a comment -

        I thought about extracting the method as well but didn't get around to doing it yet.
        To be completely correct, the close method should be in a finally block, in case of an IOException otherwise the file will remain open (I can add that, if you like)

        On a side note, I think calling the class IOUtils as well is not good since it makes the methods from the other class available only by complete package name, maybe the class could be called IOUtils2 ?

        Show
        Alexander Lehmann added a comment - I thought about extracting the method as well but didn't get around to doing it yet. To be completely correct, the close method should be in a finally block, in case of an IOException otherwise the file will remain open (I can add that, if you like) On a side note, I think calling the class IOUtils as well is not good since it makes the methods from the other class available only by complete package name, maybe the class could be called IOUtils2 ?
        Hide
        Mauro Talevi added a comment -

        If there is an IOException, I'm not sure it would be closable anyway. And in any case, the exception is handled upstream. Let's deal with this when there is a more concrete scenario to satisfy.

        As for the name of the class, there are plenty IOUtils around in several libs. The users will choose the one that they need (and if need be use the full package name). I don't like xxx2 names. They don't mean anything. Also, this IOUtils is intended for internal use, as a replacement for the commons-io one. Most likely, you won't be using it in conjunction with commons-io.

        Show
        Mauro Talevi added a comment - If there is an IOException, I'm not sure it would be closable anyway. And in any case, the exception is handled upstream. Let's deal with this when there is a more concrete scenario to satisfy. As for the name of the class, there are plenty IOUtils around in several libs. The users will choose the one that they need (and if need be use the full package name). I don't like xxx2 names. They don't mean anything. Also, this IOUtils is intended for internal use, as a replacement for the commons-io one. Most likely, you won't be using it in conjunction with commons-io.
        Hide
        Alexander Lehmann added a comment -

        I think it might be closable, depending on when the exception happened (in most cases the exception will be something like file not found or permission denied in that case the file is not open anyway), I agree that this is not a likely scenario, this is not a real problem in our case. (FindBugs sometimes complains about missing close statements in case of exception, with our source code only in TemplateableViewGenerator line 366)

        As for the class name, you are right, no argument.

        Show
        Alexander Lehmann added a comment - I think it might be closable, depending on when the exception happened (in most cases the exception will be something like file not found or permission denied in that case the file is not open anyway), I agree that this is not a likely scenario, this is not a real problem in our case. (FindBugs sometimes complains about missing close statements in case of exception, with our source code only in TemplateableViewGenerator line 366) As for the class name, you are right, no argument.
        Hide
        Mauro Talevi added a comment -

        If you want to provide a patch to close in a finally clause, by all means do.

        But let's unit test the IOUtils methods with the occasion.

        Show
        Mauro Talevi added a comment - If you want to provide a patch to close in a finally clause, by all means do. But let's unit test the IOUtils methods with the occasion.
        Hide
        Pascal Rapicault added a comment -

        I'll take a look at it tomorrow Tuesday.

        Show
        Pascal Rapicault added a comment - I'll take a look at it tomorrow Tuesday.
        Hide
        Pascal Rapicault added a comment -

        I confirm that this is now working for me.

        Show
        Pascal Rapicault added a comment - I confirm that this is now working for me.
        Mauro Talevi made changes -
        Status In Progress [ 3 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Mauro Talevi made changes -
        Component/s Core [ 11086 ]
        Mauro Talevi made changes -
        Fix Version/s 3.8 [ 19104 ]

          People

          • Assignee:
            Mauro Talevi
            Reporter:
            Pascal Rapicault
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: