Skip to content

Commit c53f41e

Browse files
committed
Avoid 'Text file busy' race when starting KafkaContainer
Fixes #11682. The container's command waits for /tmp/testcontainers_start.sh to appear, then exec's it. containerIsStarting writes the script via a single Container Archive PUT. On busy hosts the directory entry becomes visible before the docker engine has released the writer, and the immediate exec fails with ETXTBSY (exit 126). Switch to a two-file handshake: write the starter script first, then a separate /tmp/testcontainers_start.ready marker. The wait loop polls the marker instead of the script. By the time the second copyFileToContainer returns, the script's writer is fully closed, so the subsequent exec is safe. The marker file is never executed, so its own copy can race with the directory listing harmlessly.
1 parent 3878311 commit c53f41e

2 files changed

Lines changed: 9 additions & 1 deletion

File tree

modules/kafka/src/main/java/org/testcontainers/kafka/KafkaContainer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ protected void containerIsStarting(InspectContainerResponse containerInfo) {
7272

7373
command += "/etc/kafka/docker/run \n";
7474
copyFileToContainer(Transferable.of(command, 0777), STARTER_SCRIPT);
75+
// Marker file: created after the starter script copy has fully released its
76+
// writer, so the wait loop in KafkaHelper.COMMAND only proceeds when the
77+
// script is safe to execve. Without this, on busy hosts the loop can see the
78+
// starter script entry before docker-cp has closed it and fail with
79+
// "Text file busy" (exit 126).
80+
copyFileToContainer(Transferable.of(""), KafkaHelper.STARTER_SCRIPT_READY_FLAG);
7581
}
7682

7783
/**

modules/kafka/src/main/java/org/testcontainers/kafka/KafkaHelper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ class KafkaHelper {
2525

2626
static final String STARTER_SCRIPT = "/tmp/testcontainers_start.sh";
2727

28+
static final String STARTER_SCRIPT_READY_FLAG = "/tmp/testcontainers_start.ready";
29+
2830
static final String[] COMMAND = {
2931
"sh",
3032
"-c",
31-
"while [ ! -f " + STARTER_SCRIPT + " ]; do sleep 0.1; done; " + STARTER_SCRIPT,
33+
"while [ ! -f " + STARTER_SCRIPT_READY_FLAG + " ]; do sleep 0.1; done; " + STARTER_SCRIPT,
3234
};
3335

3436
static final WaitStrategy WAIT_STRATEGY = Wait.forLogMessage(".*Transitioning from RECOVERY to RUNNING.*", 1);

0 commit comments

Comments
 (0)