LDIFConnectionHandler.processLDIFFile() never leaves the loop which picks a free name for the .errors-encountered.<timestamp> file, so the LDIF connection handler thread hangs and the JVM eventually runs out of memory.
Code
opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java:474-488
String renamedPath = inputPath + ".errors-encountered." +
TimeThread.getGMTTime();
if (new File(renamedPath).exists())
{
int i=2;
while (true)
{
if (! new File(renamedPath + "." + i).exists())
{
renamedPath = renamedPath + "." + i;
}
i++;
}
}
There is no break on any path. The loop was meant to stop as soon as a free name was found, but instead it keeps going, and every iteration whose candidate name is free appends another suffix to renamedPath: x.2, x.2.3, x.2.3.4, … The string grows without bound until the thread dies with an OutOfMemoryError, having done nothing but File.exists() calls in the meantime.
How it is reached
The block runs at the end of processLDIFFile(), when the processed file could not be fully applied (errorEncountered || !fullyProcessed), and only when the target name already exists. TimeThread.getGMTTime() has a one second granularity (yyyyMMddHHmmss'Z'), so it is enough for two failed LDIF runs of the same source file to land within the same second — for example when the connection handler picks up several files in one poll, or when a test/script drops files in quickly.
The LDIF connection handler is disabled in the shipped config.ldif, so this only affects deployments which enable it.
Effect
- the connection handler thread hangs, so no further LDIF file is processed;
- memory grows until the JVM throws
OutOfMemoryError;
- the source file is never renamed out of the way, so if the handler is restarted the same file is picked up and fails again.
Suggested fix
Stop at the first free candidate:
File renamedFile = new File(renamedPath);
for (int i = 2; renamedFile.exists(); i++)
{
renamedFile = new File(renamedPath + "." + i);
}
renamedPath = renamedFile.getPath();
Found while reviewing #814 — the block sits directly above a line that PR touches, but the defect is pre-existing and unrelated to it, so it is tracked separately here.
LDIFConnectionHandler.processLDIFFile()never leaves the loop which picks a free name for the.errors-encountered.<timestamp>file, so the LDIF connection handler thread hangs and the JVM eventually runs out of memory.Code
opendj-server-legacy/src/main/java/org/opends/server/protocols/LDIFConnectionHandler.java:474-488There is no
breakon any path. The loop was meant to stop as soon as a free name was found, but instead it keeps going, and every iteration whose candidate name is free appends another suffix torenamedPath:x.2,x.2.3,x.2.3.4, … The string grows without bound until the thread dies with anOutOfMemoryError, having done nothing butFile.exists()calls in the meantime.How it is reached
The block runs at the end of
processLDIFFile(), when the processed file could not be fully applied (errorEncountered || !fullyProcessed), and only when the target name already exists.TimeThread.getGMTTime()has a one second granularity (yyyyMMddHHmmss'Z'), so it is enough for two failed LDIF runs of the same source file to land within the same second — for example when the connection handler picks up several files in one poll, or when a test/script drops files in quickly.The LDIF connection handler is disabled in the shipped
config.ldif, so this only affects deployments which enable it.Effect
OutOfMemoryError;Suggested fix
Stop at the first free candidate:
Found while reviewing #814 — the block sits directly above a line that PR touches, but the defect is pre-existing and unrelated to it, so it is tracked separately here.