v1.0.15.3 — non-blocking logger (fix install freeze), URL-encode pack file paths, news ordering by mtime

This commit is contained in:
SashegDev
2026-08-13 19:56:42 +00:00
parent 26e0280d84
commit f706e8393c
3 changed files with 68 additions and 21 deletions
@@ -9,6 +9,9 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class LauncherLogger {
@@ -17,6 +20,28 @@ public class LauncherLogger {
private static boolean initialized = false;
private static final ReentrantLock lock = new ReentrantLock();
private static final int STDOUT_QUEUE_CAPACITY = 2048;
private static final BlockingQueue<String> stdoutQueue = new LinkedBlockingQueue<>(STDOUT_QUEUE_CAPACITY);
private static final Thread stdoutWriterThread;
static {
stdoutWriterThread = new Thread(() -> {
while (true) {
try {
String line = stdoutQueue.take();
System.out.println(line);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} catch (Exception ignored) {
// stdout may be a closed or full pipe; never let it kill the writer
}
}
}, "launcher-log-stdout");
stdoutWriterThread.setDaemon(true);
stdoutWriterThread.start();
}
public static synchronized void init() {
if (initialized) return;
initialized = true;
@@ -65,31 +90,53 @@ public class LauncherLogger {
String ts = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
String line = "[" + ts + "] [" + level + "] " + msg;
System.out.println(line);
// stdout goes through a dedicated writer thread with a bounded queue so a
// full/hung stdout pipe (e.g. javaw piped to the parent exe) can never
// block application threads.
offerStdout(line);
if (t != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.flush();
System.err.print(sw.toString());
offerStdout(sw.toString());
}
if (logFile != null) {
lock.lock();
// Never block indefinitely on the file write; give up after a short wait
// so a stuck writer cannot deadlock every logging thread.
boolean acquired = false;
try {
Files.writeString(logFile, line + "\n", StandardOpenOption.APPEND);
if (t != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.flush();
Files.writeString(logFile, sw.toString(), StandardOpenOption.APPEND);
acquired = lock.tryLock(200, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
if (acquired) {
try {
Files.writeString(logFile, line + "\n", StandardOpenOption.APPEND);
if (t != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.flush();
Files.writeString(logFile, sw.toString(), StandardOpenOption.APPEND);
}
} catch (IOException e) {
System.err.println("[LauncherLogger] write error: " + e.getMessage());
} finally {
lock.unlock();
}
} catch (IOException e) {
System.err.println("[LauncherLogger] write error: " + e.getMessage());
} finally {
lock.unlock();
}
}
}
private static void offerStdout(String line) {
try {
if (!stdoutQueue.offer(line, 10, TimeUnit.MILLISECONDS)) {
// Queue full; drop rather than block the caller.
}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
}
+1 -1
View File
@@ -19,7 +19,7 @@
<properties>
<revision>1.0.15</revision>
<hotfix>2</hotfix>
<hotfix>3</hotfix>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>