mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Cleaning project fails once the binary is expanded in project explorer on Windows
Steps: ====== 1. Create a managed project and build it 2. Expand the built binary available in binary container in project explorer view 3. Now clean the project, clean will fail irrespective of number of tries you do Reason: ======= For finding the sources for binary, Elf instance is created and Section.mapSectionData creates MappedByteBuffer of channel which locks the file on Windows until its garbage collected, see following https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4715154 Solution: ========= Made ISymbolReader AutoCloseable and user is responsible to properly close it. In case of dwarf reader, we remove all the references of ByteBuffer and call gc.
This commit is contained in:
parent
571d62d6f9
commit
b10979677e
19 changed files with 144 additions and 49 deletions
|
@ -55,6 +55,10 @@ It may have other uses to other API consumers as well and is therefore included
|
|||
|
||||
This should allow ISV's to create MBS based project with a vendor-specific build-system ID without using internal API.
|
||||
|
||||
## Binary Parser code uses AutoCloseable
|
||||
|
||||
The binary parser classes which open binary files now implement AutoCloseable so they can (and should) be used in a try-with-resources block.
|
||||
See https://github.com/eclipse-cdt/cdt/pull/132
|
||||
|
||||
# Bugs Fixed in this Release
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ This section describes API removals that occurred in past releases, and upcoming
|
|||
- [Removal of deprecated CBuildConfiguration.watchProcess() methods](#watchProcessCBuildConfig)
|
||||
- [Rework of API to determine GDB command line in org.eclipse.cdt.dsf.gdb](#gdbBackendDebuggerCommandLine)
|
||||
- [Removal of Qt plug-ins and features](#qt-plugins)
|
||||
- [Removal of constructor org.eclipse.cdt.utils.coff.CodeViewReader(RandomAccessFile, int, boolean)](#CodeViewReader-constructor-removal)
|
||||
|
||||
## API Changes in CDT 10.5.0
|
||||
|
||||
|
@ -163,6 +164,14 @@ The following bundles and all their related API has been removed:
|
|||
|
||||
See https://github.com/eclipse-cdt/cdt/issues/123
|
||||
|
||||
### <span id="CodeViewReader-constructor-removal">Removal of constructor org.eclipse.cdt.utils.coff.CodeViewReader(RandomAccessFile, int, boolean)</span>
|
||||
|
||||
Same instance of RandomAccessFile was shared between multiple objects which
|
||||
causes problems in closing it properly. A new constructor is introduced which
|
||||
accepts filename and opens a RandomAccessFile.
|
||||
|
||||
See https://github.com/eclipse-cdt/cdt/pull/132
|
||||
|
||||
---
|
||||
|
||||
## API Changes in CDT 10.5.0.
|
||||
|
|
|
@ -306,11 +306,14 @@ public class Binary extends Openable implements IBinary {
|
|||
// Try to get the list of source files used to build the binary from the
|
||||
// symbol information.
|
||||
|
||||
ISymbolReader symbolreader = obj.getAdapter(ISymbolReader.class);
|
||||
if (symbolreader == null)
|
||||
return false;
|
||||
String[] sourceFiles = null;
|
||||
try (ISymbolReader symbolreader = obj.getAdapter(ISymbolReader.class)) {
|
||||
if (symbolreader == null)
|
||||
return false;
|
||||
|
||||
sourceFiles = symbolreader.getSourceFiles();
|
||||
}
|
||||
|
||||
String[] sourceFiles = symbolreader.getSourceFiles();
|
||||
if (sourceFiles != null && sourceFiles.length > 0) {
|
||||
ISourceFinder srcFinder = getAdapter(ISourceFinder.class);
|
||||
try {
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
|||
* @noextend This interface is not intended to be extended by clients.
|
||||
* @noimplement This interface is not intended to be implemented by clients.
|
||||
*/
|
||||
public interface ISymbolReader {
|
||||
public interface ISymbolReader extends AutoCloseable {
|
||||
|
||||
String[] getSourceFiles();
|
||||
|
||||
|
@ -35,4 +35,7 @@ public interface ISymbolReader {
|
|||
* @since 5.2
|
||||
*/
|
||||
String[] getSourceFiles(IProgressMonitor monitor);
|
||||
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.utils.coff;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
|
@ -30,14 +31,44 @@ public class CodeViewReader implements ISymbolReader {
|
|||
private String[] files = null;
|
||||
private boolean parsed = false;
|
||||
|
||||
public CodeViewReader(RandomAccessFile accessFile, int dataOffset, boolean littleEndian) {
|
||||
file = accessFile;
|
||||
/**
|
||||
* @since 8.0
|
||||
*/
|
||||
public CodeViewReader(String filename, int dataOffset, boolean littleEndian) throws FileNotFoundException {
|
||||
file = new RandomAccessFile(filename, "r"); //$NON-NLS-1$
|
||||
cvData = dataOffset;
|
||||
isLe = littleEndian;
|
||||
|
||||
fileList = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 8.0
|
||||
*/
|
||||
public void dispose() {
|
||||
if (file != null) {
|
||||
try {
|
||||
file.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
file = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
dispose();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSourceFiles() {
|
||||
if (!parsed) {
|
||||
|
|
|
@ -579,13 +579,16 @@ public class PE implements AutoCloseable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
public void dispose() throws IOException {
|
||||
public void dispose() {
|
||||
if (rfile != null) {
|
||||
rfile.close();
|
||||
try {
|
||||
rfile.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
rfile = null;
|
||||
}
|
||||
}
|
||||
|
@ -771,7 +774,6 @@ public class PE implements AutoCloseable {
|
|||
}
|
||||
|
||||
private ISymbolReader createCodeViewReader() {
|
||||
ISymbolReader symReader = null;
|
||||
final int IMAGE_DIRECTORY_ENTRY_DEBUG = 6;
|
||||
|
||||
try {
|
||||
|
@ -813,8 +815,7 @@ public class PE implements AutoCloseable {
|
|||
String s2 = accessFile.readLine();
|
||||
if (s2.startsWith("NB11")) { //$NON-NLS-1$
|
||||
Attribute att = getAttribute();
|
||||
symReader = new CodeViewReader(accessFile, debugBase, att.isLittleEndian());
|
||||
return symReader;
|
||||
return new CodeViewReader(filename, debugBase, att.isLittleEndian());
|
||||
}
|
||||
}
|
||||
fileOffset += dir.DEBUGDIRSZ;
|
||||
|
@ -825,7 +826,7 @@ public class PE implements AutoCloseable {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return symReader;
|
||||
return null;
|
||||
}
|
||||
|
||||
private ISymbolReader createStabsReader() {
|
||||
|
|
|
@ -673,13 +673,16 @@ public class PE64 implements AutoCloseable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
public void dispose() throws IOException {
|
||||
public void dispose() {
|
||||
if (rfile != null) {
|
||||
rfile.close();
|
||||
try {
|
||||
rfile.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
rfile = null;
|
||||
}
|
||||
}
|
||||
|
@ -881,7 +884,6 @@ public class PE64 implements AutoCloseable {
|
|||
}
|
||||
|
||||
private ISymbolReader createCodeViewReader() {
|
||||
ISymbolReader symReader = null;
|
||||
final int IMAGE_DIRECTORY_ENTRY_DEBUG = 6;
|
||||
|
||||
try {
|
||||
|
@ -942,8 +944,7 @@ public class PE64 implements AutoCloseable {
|
|||
String s2 = accessFile.readLine();
|
||||
if (s2.startsWith("NB11")) { //$NON-NLS-1$
|
||||
Attribute att = getAttribute();
|
||||
symReader = new CodeViewReader(accessFile, debugBase, att.isLittleEndian());
|
||||
return symReader;
|
||||
return new CodeViewReader(filename, debugBase, att.isLittleEndian());
|
||||
}
|
||||
}
|
||||
fileOffset += dir.DEBUGDIRSZ;
|
||||
|
@ -954,7 +955,7 @@ public class PE64 implements AutoCloseable {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return symReader;
|
||||
return null;
|
||||
}
|
||||
|
||||
private ISymbolReader createStabsReader() {
|
||||
|
|
|
@ -107,9 +107,10 @@ public class PEBinaryObject extends BinaryObjectAdapter {
|
|||
}
|
||||
}
|
||||
if (adapter.equals(ISymbolReader.class)) {
|
||||
PE pe = getAdapter(PE.class);
|
||||
if (pe != null) {
|
||||
return (T) pe.getSymbolReader();
|
||||
try (PE pe = getAdapter(PE.class)) {
|
||||
if (pe != null) {
|
||||
return (T) pe.getSymbolReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getAdapter(adapter);
|
||||
|
|
|
@ -109,9 +109,10 @@ public class PEBinaryObject64 extends BinaryObjectAdapter {
|
|||
}
|
||||
}
|
||||
if (adapter.equals(ISymbolReader.class)) {
|
||||
PE64 pe = getAdapter(PE64.class);
|
||||
if (pe != null) {
|
||||
return (T) pe.getSymbolReader();
|
||||
try (PE64 pe = getAdapter(PE64.class)) {
|
||||
if (pe != null) {
|
||||
return (T) pe.getSymbolReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getAdapter(adapter);
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.eclipse.cdt.utils.elf.Elf.Section;
|
|||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
public class Dwarf {
|
||||
public class Dwarf implements AutoCloseable {
|
||||
|
||||
/* Section names. */
|
||||
final static String DWARF_DEBUG_INFO = ".debug_info"; //$NON-NLS-1$
|
||||
|
@ -359,6 +359,26 @@ public class Dwarf {
|
|||
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
dwarfSections.clear();
|
||||
dwarfAltSections.clear();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
dispose();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
int read_4_bytes(ByteBuffer in) throws IOException {
|
||||
try {
|
||||
byte[] bytes = new byte[4];
|
||||
|
|
|
@ -248,4 +248,7 @@ public class StabsReader implements ISymbolReader {
|
|||
return getSourceFiles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ public class Elf implements AutoCloseable {
|
|||
private Symbol[] symbolsTable;
|
||||
/** .dynSym section */
|
||||
private Symbol[] dynamicSymbols;
|
||||
private boolean areSectionsMapped; // Have sections been mapped? Used to clean up properly in Elf.Dispose.
|
||||
|
||||
protected String EMPTY_STRING = ""; //$NON-NLS-1$
|
||||
private long elfOffset;
|
||||
|
@ -339,7 +338,6 @@ public class Elf implements AutoCloseable {
|
|||
*/
|
||||
public ByteBuffer mapSectionData() throws IOException {
|
||||
makeSureNotCompressed();
|
||||
areSectionsMapped = true;
|
||||
return efile.getChannel().map(MapMode.READ_ONLY, sh_offset, sh_size).load().asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
|
@ -987,9 +985,6 @@ public class Elf implements AutoCloseable {
|
|||
if (efile != null) {
|
||||
efile.close();
|
||||
efile = null;
|
||||
// ensure the mappings get cleaned up
|
||||
if (areSectionsMapped)
|
||||
System.gc();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
@ -1304,6 +1299,12 @@ public class Elf implements AutoCloseable {
|
|||
return reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new symbol reader instance on each call. Caller is responsible for closing
|
||||
* the symbol reader
|
||||
*
|
||||
* @return symbol reader or {@code null} if couldn't create symbol reader
|
||||
*/
|
||||
public ISymbolReader getSymbolReader() {
|
||||
ISymbolReader reader = null;
|
||||
reader = createDwarfReader();
|
||||
|
|
|
@ -187,9 +187,10 @@ public class ElfBinaryObject extends BinaryObjectAdapter {
|
|||
}
|
||||
}
|
||||
if (adapter.equals(ISymbolReader.class)) {
|
||||
Elf elf = getAdapter(Elf.class);
|
||||
if (elf != null) {
|
||||
return (T) elf.getSymbolReader();
|
||||
try (Elf elf = getAdapter(Elf.class)) {
|
||||
if (elf != null) {
|
||||
return (T) elf.getSymbolReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getAdapter(adapter);
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.eclipse.cdt.utils.debug.stabs.StabsReader;
|
|||
* This class is planned for removal in next major release.
|
||||
*/
|
||||
@Deprecated
|
||||
public class MachO {
|
||||
public class MachO implements AutoCloseable {
|
||||
protected ERandomAccessFile efile;
|
||||
|
||||
protected MachOhdr mhdr;
|
||||
|
@ -1109,6 +1109,11 @@ public class MachO {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (cppFilt != null) {
|
||||
cppFilt.dispose();
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.eclipse.cdt.utils.debug.stabs.StabsReader;
|
|||
/**
|
||||
* @since 5.2
|
||||
*/
|
||||
public class MachO64 {
|
||||
public class MachO64 implements AutoCloseable {
|
||||
protected ERandomAccessFile efile;
|
||||
|
||||
protected MachOhdr mhdr;
|
||||
|
@ -1184,6 +1184,11 @@ public class MachO64 {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (cppFilt != null) {
|
||||
cppFilt.dispose();
|
||||
|
|
|
@ -395,9 +395,10 @@ public class MachOBinaryObject extends BinaryObjectAdapter {
|
|||
}
|
||||
}
|
||||
if (adapter.equals(ISymbolReader.class)) {
|
||||
MachO macho = getAdapter(MachO.class);
|
||||
if (macho != null) {
|
||||
return (T) macho.getSymbolReader();
|
||||
try (MachO macho = getAdapter(MachO.class)) {
|
||||
if (macho != null) {
|
||||
return (T) macho.getSymbolReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getAdapter(adapter);
|
||||
|
|
|
@ -410,9 +410,10 @@ public class MachOBinaryObject64 extends BinaryObjectAdapter {
|
|||
}
|
||||
}
|
||||
if (adapter.equals(ISymbolReader.class)) {
|
||||
MachO64 macho = getAdapter(MachO64.class);
|
||||
if (macho != null) {
|
||||
return (T) macho.getSymbolReader();
|
||||
try (MachO64 macho = getAdapter(MachO64.class)) {
|
||||
if (macho != null) {
|
||||
return (T) macho.getSymbolReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getAdapter(adapter);
|
||||
|
|
|
@ -66,6 +66,7 @@ public class CompilerOptionParser implements IWorkspaceRunnable {
|
|||
|
||||
@Override
|
||||
public void run(IProgressMonitor monitor) {
|
||||
ISymbolReader reader = null;
|
||||
try {
|
||||
// Calculate how many source files we have to process and use that as a basis
|
||||
// for our work estimate.
|
||||
|
@ -102,7 +103,7 @@ public class CompilerOptionParser implements IWorkspaceRunnable {
|
|||
return;
|
||||
}
|
||||
|
||||
ISymbolReader reader = bf.getAdapter(ISymbolReader.class);
|
||||
reader = bf.getAdapter(ISymbolReader.class);
|
||||
String[] sourceFiles = reader.getSourceFiles();
|
||||
monitor.beginTask(Messages.GetCompilerOptions, sourceFiles.length * 2 + 1);
|
||||
|
||||
|
@ -157,6 +158,9 @@ public class CompilerOptionParser implements IWorkspaceRunnable {
|
|||
e.printStackTrace();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
} finally {
|
||||
if (reader != null)
|
||||
reader.close();
|
||||
}
|
||||
monitor.done();
|
||||
}
|
||||
|
|
|
@ -120,11 +120,11 @@ public class StandardSourceFilesProvider extends PlatformObject implements ISour
|
|||
|
||||
IBinaryFile bin = createBinaryFile(executable);
|
||||
if (bin != null) {
|
||||
ISymbolReader symbolreader = bin.getAdapter(ISymbolReader.class);
|
||||
if (symbolreader != null) {
|
||||
return symbolreader.getSourceFiles(monitor);
|
||||
try (ISymbolReader symbolreader = bin.getAdapter(ISymbolReader.class)) {
|
||||
if (symbolreader != null) {
|
||||
return symbolreader.getSourceFiles(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue