Skip to content

Commit 9f2cbf1

Browse files
committed
Try to avoid racy cleanups
1 parent fe0aeca commit 9f2cbf1

File tree

1 file changed

+33
-12
lines changed
  • dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller

1 file changed

+33
-12
lines changed

dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/TempLocationManager.java

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import java.nio.file.Paths;
1212
import java.nio.file.attribute.BasicFileAttributes;
1313
import java.nio.file.attribute.PosixFilePermissions;
14+
import java.time.Instant;
15+
import java.time.temporal.ChronoUnit;
1416
import java.util.Set;
1517
import java.util.concurrent.CompletableFuture;
1618
import org.slf4j.Logger;
@@ -35,9 +37,11 @@ private class CleanupVisitor implements FileVisitor<Path> {
3537
private final Set<String> pidSet = PidHelper.getJavaPids();
3638

3739
private final boolean cleanSelf;
40+
private final Instant cutoff;
3841

3942
CleanupVisitor(boolean cleanSelf) {
4043
this.cleanSelf = cleanSelf;
44+
this.cutoff = Instant.now().minus(cutoffSeconds, ChronoUnit.SECONDS);
4145
}
4246

4347
@Override
@@ -59,6 +63,9 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
5963

6064
@Override
6165
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
66+
if (Files.getLastModifiedTime(file).toInstant().isAfter(cutoff)) {
67+
return FileVisitResult.SKIP_SUBTREE;
68+
}
6269
Files.delete(file);
6370
return FileVisitResult.CONTINUE;
6471
}
@@ -85,6 +92,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx
8592

8693
private final Path baseTempDir;
8794
private final Path tempDir;
95+
private final long cutoffSeconds;
8896

8997
private final CompletableFuture<Void> cleanupTask;
9098

@@ -117,6 +125,19 @@ private TempLocationManager() {
117125
}
118126

119127
TempLocationManager(ConfigProvider configProvider) {
128+
// In order to avoid racy attempts to clean up files which are currently being processed in a
129+
// JVM which is being shut down (the JVMs far in the shutdown routine may not be reported by
130+
// 'jps' but still can be eg. processing JFR chunks) we will not clean up any files not older
131+
// than '2 * PROFILING_UPLOAD_PERIOD' seconds.
132+
// The reasoning is that even if the file is created immediately at JVM startup once it is
133+
// 'PROFILING_UPLOAD_PERIOD' seconds old it gets processed to upload the final profile data and
134+
// this processing will not take longer than another `PROFILING_UPLOAD_PERIOD' seconds.
135+
// This is just an assumption but as long as the profiled application is working normally (eg.
136+
// OS is not stalling) this assumption will hold.
137+
cutoffSeconds =
138+
configProvider.getLong(
139+
ProfilingConfig.PROFILING_UPLOAD_PERIOD,
140+
ProfilingConfig.PROFILING_UPLOAD_PERIOD_DEFAULT);
120141
Path configuredTempDir =
121142
Paths.get(
122143
configProvider.getString(
@@ -140,21 +161,21 @@ private TempLocationManager() {
140161
tempDir = baseTempDir.resolve("pid_" + pid);
141162
cleanupTask = CompletableFuture.runAsync(() -> cleanup(false));
142163

143-
// Runtime.getRuntime()
144-
// .addShutdownHook(
145-
// new Thread(
146-
// () -> {
147-
// try {
148-
// cleanupTask.join();
149-
// } finally {
150-
// cleanup(true);
151-
// }
152-
// },
153-
// "Temp Location Manager Cleanup"));
164+
Runtime.getRuntime()
165+
.addShutdownHook(
166+
new Thread(
167+
() -> {
168+
try {
169+
cleanupTask.join();
170+
} finally {
171+
cleanup(true);
172+
}
173+
},
174+
"Temp Location Manager Cleanup"));
154175
}
155176

156177
/**
157-
* Get the temporary directory for the current process.
178+
* Get the temporary directory for the current process. The directory will be removed at JVM exit.
158179
*
159180
* @return the temporary directory for the current process
160181
*/

0 commit comments

Comments
 (0)