Skip to content

LDIF connection handler hangs in an infinite loop when the .errors-encountered file name is taken #828

Description

@vharseko

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugjavaPull requests that update java code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions