From 955bd297b2038127a7e9c8d941430e790792e44c Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Mon, 16 Apr 2012 14:41:19 -0400 Subject: [PATCH] Workaround for Java problem on Windows with releasing buffers for memory-mapped files java.io.FileNotFoundException: C:\workspace\junit-workspace\.metadata\.plugins\org.eclipse.cdt.core\language.settings.xml (The requested operation cannot be performed on a file with a user-mapped section open) at java.io.FileOutputStream.open(Native Method) at java.io.FileOutputStream.(Unknown Source) at java.io.FileOutputStream.(Unknown Source) at org.eclipse.cdt.internal.core.XmlUtil.getFileOutputStreamWorkaround(XmlUtil.java:315) at org.eclipse.cdt.internal.core.XmlUtil.serializeXml(XmlUtil.java:290) at org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace(LanguageSettingsProvidersSerializer.java:539) at org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer$1.runInWorkspace(LanguageSettingsProvidersSerializer.java:577) at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:38) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54) --- .../eclipse/cdt/internal/core/XmlUtil.java | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java index f996e5e26c3..76ffb5efe70 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/XmlUtil.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -228,13 +229,16 @@ public class XmlUtil { return null; } - InputStream xmlStream; try { - xmlStream = new FileInputStream(xmlFile); + InputStream xmlStream = new FileInputStream(xmlFile); + try { + return loadXml(xmlStream); + } finally { + xmlStream.close(); + } } catch (Exception e) { throw new CoreException(CCorePlugin.createStatus(Messages.XmlUtil_InternalErrorLoading, e)); } - return loadXml(xmlStream); } /** @@ -245,8 +249,16 @@ public class XmlUtil { * @throws CoreException if something goes wrong. */ public static Document loadXml(IFile xmlFile) throws CoreException { - InputStream xmlStream = xmlFile.getContents(); - return loadXml(xmlStream); + try { + InputStream xmlStream = xmlFile.getContents(); + try { + return loadXml(xmlStream); + } finally { + xmlStream.close(); + } + } catch (Exception e) { + throw new CoreException(CCorePlugin.createStatus(Messages.XmlUtil_InternalErrorLoading, e)); + } } /** @@ -273,13 +285,46 @@ public class XmlUtil { XmlUtil.prettyFormat(doc); DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(new FileOutputStream(storeFile)); + StreamResult result = new StreamResult(getFileOutputStreamWorkaround(storeFile)); transformer.transform(source, result); result.getOutputStream().close(); ResourcesUtil.refreshWorkspaceFiles(uriLocation); } + /** + * Workaround for Java problem on Windows with releasing buffers for memory-mapped files. + * + * @see "http://stackoverflow.com/questions/3602783/file-access-synchronized-on-java-object" + * @see "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6354433" + * @see "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154" + * @see "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4469299" + */ + private static FileOutputStream getFileOutputStreamWorkaround(java.io.File storeFile) throws FileNotFoundException { + final int maxCount = 10; + for (int i = 0; i <= maxCount; i++) { + try { + // there is no sleep on first round + Thread.sleep(10 * i); + } catch (InterruptedException e) { + // restore interrupted status + Thread.currentThread().interrupt(); + } + try { + return new FileOutputStream(storeFile); + } catch (FileNotFoundException e) { + // only apply workaround for the very specific exception + if (i >= maxCount || !e.getMessage().contains("The requested operation cannot be performed on a file with a user-mapped section open")) { //$NON-NLS-1$ + throw e; + } +// CCorePlugin.log(new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID, "Workaround for concurrent access to memory-mapped files applied, attempt " + (i + 1), e)); //$NON-NLS-1$ + } + } + + // will never get here + return null; + } + /** * Serialize XML Document into a byte array. * @param doc - DOM Document to serialize.