mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
# Description of Changes <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: James Brunton <jbrunton96@gmail.com>
130 lines
4.4 KiB
Java
130 lines
4.4 KiB
Java
import java.io.*;
|
|
import java.nio.file.*;
|
|
import java.util.*;
|
|
|
|
/**
|
|
* RestartHelper - Lightweight utility to restart Stirling-PDF
|
|
*
|
|
* This helper waits for the old process to exit, then starts the app again
|
|
* with the same arguments. It's only active during restart and then exits.
|
|
*
|
|
* Usage:
|
|
* java -jar restart-helper.jar --pid 1234 --app /path/app.jar
|
|
* [--java /path/to/java] [--argsFile /path/args.txt]
|
|
* [--backoffMs 1000]
|
|
*/
|
|
public class RestartHelper {
|
|
public static void main(String[] args) {
|
|
try {
|
|
Map<String, String> cli = parseArgs(args);
|
|
|
|
long pid = Long.parseLong(req(cli, "pid"));
|
|
Path appJar = Paths.get(req(cli, "app")).toAbsolutePath().normalize();
|
|
String javaBin = cli.getOrDefault("java", "java");
|
|
Path argsFile = cli.containsKey("argsFile") ? Paths.get(cli.get("argsFile")) : null;
|
|
long backoffMs = Long.parseLong(cli.getOrDefault("backoffMs", "1000"));
|
|
|
|
if (!Files.isRegularFile(appJar)) {
|
|
fail("App jar not found: " + appJar);
|
|
}
|
|
|
|
System.out.println("[restart-helper] Waiting for PID " + pid + " to exit...");
|
|
waitForPidToExit(pid);
|
|
|
|
// Brief pause to allow ports/files to release
|
|
if (backoffMs > 0) {
|
|
Thread.sleep(backoffMs);
|
|
}
|
|
|
|
List<String> cmd = new ArrayList<>();
|
|
cmd.add(javaBin);
|
|
cmd.add("-jar");
|
|
cmd.add(appJar.toString());
|
|
|
|
// Load application arguments from file if provided
|
|
if (argsFile != null && Files.isRegularFile(argsFile)) {
|
|
for (String line : Files.readAllLines(argsFile)) {
|
|
if (!line.isBlank()) {
|
|
cmd.add(line.trim());
|
|
}
|
|
}
|
|
// Clean up args file after reading
|
|
try {
|
|
Files.deleteIfExists(argsFile);
|
|
} catch (IOException ignored) {
|
|
// Best effort cleanup
|
|
}
|
|
}
|
|
|
|
System.out.println("[restart-helper] Starting app: " + String.join(" ", cmd));
|
|
ProcessBuilder pb = new ProcessBuilder(cmd);
|
|
pb.inheritIO(); // Forward logs to same console/service logs
|
|
pb.start();
|
|
|
|
// Exit immediately - leave app running
|
|
System.out.println("[restart-helper] App restarted successfully. Helper exiting.");
|
|
System.exit(0);
|
|
|
|
} catch (Exception e) {
|
|
System.err.println("[restart-helper] ERROR: " + e.getMessage());
|
|
e.printStackTrace();
|
|
System.exit(2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wait for the specified PID to exit
|
|
*/
|
|
private static void waitForPidToExit(long pid) throws InterruptedException {
|
|
try {
|
|
// Java 9+: ProcessHandle API
|
|
Optional<ProcessHandle> ph = ProcessHandle.of(pid);
|
|
while (ph.isPresent() && ph.get().isAlive()) {
|
|
Thread.sleep(300);
|
|
ph = ProcessHandle.of(pid);
|
|
}
|
|
} catch (Throwable t) {
|
|
// Fallback for older JDKs or if ProcessHandle isn't available
|
|
// Just sleep a bit - by the time main exits, socket should be freed
|
|
System.out.println("[restart-helper] ProcessHandle not available, using fallback wait");
|
|
Thread.sleep(2000);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse command-line arguments in --key value format
|
|
*/
|
|
private static Map<String, String> parseArgs(String[] args) {
|
|
Map<String, String> map = new HashMap<>();
|
|
for (int i = 0; i < args.length; i++) {
|
|
if (args[i].startsWith("--")) {
|
|
String key = args[i].substring(2);
|
|
String val = (i + 1 < args.length && !args[i + 1].startsWith("--"))
|
|
? args[++i]
|
|
: "true";
|
|
map.put(key, val);
|
|
}
|
|
}
|
|
return map;
|
|
}
|
|
|
|
/**
|
|
* Get required parameter or fail
|
|
*/
|
|
private static String req(Map<String, String> map, String key) {
|
|
String val = map.get(key);
|
|
if (val == null || val.isBlank()) {
|
|
fail("Missing required parameter: --" + key);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* Print error and exit
|
|
*/
|
|
private static void fail(String message) {
|
|
System.err.println("[restart-helper] ERROR: " + message);
|
|
System.exit(2);
|
|
}
|
|
}
|