Community
Participate
Working Groups
If Eclipse detects that a file is locked during a build, it writes something similar to the following to the log. This is a normal condition, not a bug in Eclipse. As such, reporting it to the user in a problem marker is sufficient. It should not be logged. !MESSAGE Could not delete: /org.eclipse.ui.ide/bin/org. !STACK 1 org.eclipse.core.internal.resources.ResourceException: Problems encountered while deleting resources. at org.eclipse.core.internal.localstore.FileSystemResourceManager.delete(FileSystemResourceManager.java:182) at org.eclipse.core.internal.resources.ResourceTree.standardDeleteFolder(ResourceTree.java:614) at org.eclipse.core.internal.resources.Resource.unprotectedDelete(Resource.java:1553) at org.eclipse.core.internal.resources.Resource.delete(Resource.java:664) at org.eclipse.jdt.internal.core.builder.BatchImageBuilder.cleanOutputFolders(BatchImageBuilder.java:126) at org.eclipse.jdt.internal.core.builder.BatchImageBuilder.build(BatchImageBuilder.java:36) at org.eclipse.jdt.internal.core.builder.JavaBuilder.buildAll(JavaBuilder.java:216) at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:148) at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:593) at org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:1038) at org.eclipse.core.runtime.Platform.run(Platform.java:775) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:168) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:202) at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:231) at org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:1038) at org.eclipse.core.runtime.Platform.run(Platform.java:775) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:234) at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:253) at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:282) at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:139) at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:200) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:67)
I agree that the error showing up in the log is somewhat unfortunate. At the moment being, though, the error message in the interface is far from being perfect as far as helping the user to fix his error in concerned (merely tells that a class file was not written - not even saying which), while the log neatly tells which file failed and why. I will then retitle this bug as '[builder] improve the error handling in case the build encounters a locked file within the the output folder' and I would attempt to improve the error message before cleansing the log.
Reconsidering... In fact, the error log only tells us who fails to delete, not what could not be deleted. Will investigate doing better here. Reproducing the case needs some talent under Windows/NTFS, because marking a directory as read only does not prevent anyone from deleting its subparts (nor from creating subparts in it either). One way of doing the trick is to create a read-only directory and to install a non-empty, non-readable subdirectory in it. The attempt to delete the first directory then fails. Under Linux, simply create a non-empty, read-only directory.
(Another way to reproduce the bug under Windows is to edit a text file in the to be deleted directory. This does not cope that well with our automated tests though.)
(In reply to comment #2) ... > In fact, the error log only tells us who fails to delete, not what could not be > deleted. Wrong, the log tells us what could not be deleted, /org.eclipse.ui.ide/bin/org in this instance. Hence the log is precise enough.
Taking a closer look at why we log this, it appears to me that we (JDT build) tend to log all filesystem related errors that have reasonable chances to happen because of conditions that are out of the control of Eclipse. While there exist means for the user to create the condition that generates the error above from within Eclipse (at least under Linux: proceed to the Resource perspective and change a non-empty output folder to read-only), those means are somewhat convoluted (need to get out of the Java perspective for the scenario I spell out above), and there is no easy quick-fix implemented. It is more probable that the problems arise from the use of external tools. I would contend that this apparent weakness comes from the fact that Eclipse does not take definite ownership of the underlying filesystem areas, and cannot control the exclusive access to it via itself. All in all, we would then maintain the log. There may remain an issue with the message itself.
There is one case for which we get an imprecise message: doing a clean without an immediate build when the output folder is read-only. In cases where a build really happens (not clean only), the message includes the name of the precise resource that could not be deleted. The behavior in case of a build is that the first file that cannot get deleted is reported (the choice is somewhat arbitrary). This has a drawback: the cause may be attached to another entry in the file system, aka the parent directory. But this has an advantage over only telling the user that something could not be deleted in the project, in that it gives a pointer to a precise file that got affected. Accordingly, I'll attempt to get the same behavior (message with file picked up randomly amongst files that could not be deleted) for the clean only scenario.
We have two places where we call getLocalizedMessage upon a CoreException instead of an ImageBuilderInternalException. The latter takes care of fetching the first child in case of a multi-status, which the former does not do. Experimenting a patch that delegates the elaboration of the error message to a dedicated method instead of calling CoreException#getLocalizedMessage straight away.
Created attachment 70327 [details] Experimental fix plus test case
Tests pass. Kent, would you please tell me what you think, especially re. where we should put the exception formatting code?
Created attachment 72726 [details] What about this instead ? My preference would be to put it in the JavaBuilder & remove getLocalizedMessage() from ImageBuilderInternalException. Its only sent from the JavaBuilder when we're building markers so it would make more sense to include it there. We could replace the 3 references to Messages.build_inconsistentProject with a single call to a helper method that took the exception.
Looks good. Will combine patches and release when tests complete.
Created attachment 73518 [details] Fix + test case This patch combines Kent's for the code with mine for the test, further tuned to pass ErrorsTests under Linux (the added test won't cope with Windozes as is - JDK 6 has APIs that would allow this, but we cannot use it). Other tests currently running.
Released for 3.4 M1.
Verified for 3.4M1 using build I20070802-0800.