diff options
Diffstat (limited to 'src/main/java/net/fabricmc/loom/util')
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/IOStringConsumer.java | 31 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/OperatingSystem.java | 16 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/SourceRemapper.java | 6 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/gradle/ProgressLoggerHelper.java (renamed from src/main/java/net/fabricmc/loom/util/gradle/ProgressLogger.java) | 18 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/gradle/ThreadedProgressLoggerConsumer.java | 95 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/gradle/ThreadedSimpleProgressLogger.java | 36 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/gradle/WorkerDaemonClientsManagerHelper.java | 77 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/ipc/IPCClient.java | 67 | ||||
-rw-r--r-- | src/main/java/net/fabricmc/loom/util/ipc/IPCServer.java | 88 |
9 files changed, 422 insertions, 12 deletions
diff --git a/src/main/java/net/fabricmc/loom/util/IOStringConsumer.java b/src/main/java/net/fabricmc/loom/util/IOStringConsumer.java new file mode 100644 index 00000000..2459b3a9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/IOStringConsumer.java @@ -0,0 +1,31 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util; + +import java.io.IOException; + +public interface IOStringConsumer { + void accept(String data) throws IOException; +} diff --git a/src/main/java/net/fabricmc/loom/util/OperatingSystem.java b/src/main/java/net/fabricmc/loom/util/OperatingSystem.java index 38e2eb4a..9df41edb 100644 --- a/src/main/java/net/fabricmc/loom/util/OperatingSystem.java +++ b/src/main/java/net/fabricmc/loom/util/OperatingSystem.java @@ -24,6 +24,11 @@ package net.fabricmc.loom.util; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.StandardProtocolFamily; +import java.nio.channels.ServerSocketChannel; + public class OperatingSystem { public static String getOS() { String osName = System.getProperty("os.name").toLowerCase(); @@ -63,4 +68,15 @@ public class OperatingSystem { // CI seems to be set by most popular CI services return System.getenv("CI") != null; } + + // Requires Unix, or Windows 10 17063 or later. See: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ + public static boolean isUnixDomainSocketsSupported() { + try (ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX)) { + return true; + } catch (UnsupportedOperationException e) { + return false; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } } diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index ec1ce8a3..776fa6e3 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -43,7 +43,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; -import net.fabricmc.loom.util.gradle.ProgressLogger; +import net.fabricmc.loom.util.gradle.ProgressLoggerHelper; import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.stitch.util.StitchUtil; @@ -51,7 +51,7 @@ import net.fabricmc.stitch.util.StitchUtil; public class SourceRemapper { private final Project project; private final boolean toNamed; - private final List<Consumer<ProgressLogger>> remapTasks = new ArrayList<>(); + private final List<Consumer<ProgressLoggerHelper>> remapTasks = new ArrayList<>(); private Mercury mercury; @@ -90,7 +90,7 @@ public class SourceRemapper { project.getLogger().lifecycle(":remapping sources"); - ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, SourceRemapper.class.getName()); + ProgressLoggerHelper progressLogger = ProgressLoggerHelper.getProgressFactory(project, SourceRemapper.class.getName()); progressLogger.start("Remapping dependency sources", "sources"); remapTasks.forEach(consumer -> consumer.accept(progressLogger)); diff --git a/src/main/java/net/fabricmc/loom/util/gradle/ProgressLogger.java b/src/main/java/net/fabricmc/loom/util/gradle/ProgressLoggerHelper.java index 2b3d180e..d2fb1a4a 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/ProgressLogger.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/ProgressLoggerHelper.java @@ -32,11 +32,11 @@ import org.gradle.api.Project; /** * Wrapper to ProgressLogger internal API. */ -public class ProgressLogger { +public class ProgressLoggerHelper { private final Object logger; private final Method getDescription, setDescription, getShortDescription, setShortDescription, getLoggingHeader, setLoggingHeader, start, started, startedArg, progress, completed, completedArg; - private ProgressLogger(Object logger) { + private ProgressLoggerHelper(Object logger) { this.logger = logger; this.getDescription = getMethod("getDescription"); this.setDescription = getMethod("setDescription", String.class); @@ -102,17 +102,17 @@ public class ProgressLogger { * @param category The logger category * @return In any case a progress logger */ - public static ProgressLogger getProgressFactory(Project project, String category) { + public static ProgressLoggerHelper getProgressFactory(Project project, String category) { try { Method getServices = project.getClass().getMethod("getServices"); Object serviceFactory = getServices.invoke(project); Method get = serviceFactory.getClass().getMethod("get", Class.class); Object progressLoggerFactory = get.invoke(serviceFactory, getFactoryClass()); Method newOperation = progressLoggerFactory.getClass().getMethod("newOperation", String.class); - return new ProgressLogger(newOperation.invoke(progressLoggerFactory, category)); + return new ProgressLoggerHelper(newOperation.invoke(progressLoggerFactory, category)); } catch (Exception e) { project.getLogger().error("Unable to get progress logger. Download progress will not be displayed."); - return new ProgressLogger(null); + return new ProgressLoggerHelper(null); } } @@ -132,7 +132,7 @@ public class ProgressLogger { * * @param description The description. */ - public ProgressLogger setDescription(String description) { + public ProgressLoggerHelper setDescription(String description) { invoke(setDescription, description); return this; } @@ -153,7 +153,7 @@ public class ProgressLogger { * * @param description The short description. */ - public ProgressLogger setShortDescription(String description) { + public ProgressLoggerHelper setShortDescription(String description) { invoke(setShortDescription, description); return this; } @@ -176,7 +176,7 @@ public class ProgressLogger { * * @param header The header. May be empty or null. */ - public ProgressLogger setLoggingHeader(String header) { + public ProgressLoggerHelper setLoggingHeader(String header) { invoke(setLoggingHeader, header); return this; } @@ -186,7 +186,7 @@ public class ProgressLogger { * * @return this logger instance */ - public ProgressLogger start(String description, String shortDescription) { + public ProgressLoggerHelper start(String description, String shortDescription) { invoke(start, description, shortDescription); return this; } diff --git a/src/main/java/net/fabricmc/loom/util/gradle/ThreadedProgressLoggerConsumer.java b/src/main/java/net/fabricmc/loom/util/gradle/ThreadedProgressLoggerConsumer.java new file mode 100644 index 00000000..94f49eed --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/gradle/ThreadedProgressLoggerConsumer.java @@ -0,0 +1,95 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util.gradle; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import org.gradle.api.Project; +import org.gradle.api.internal.project.ProjectInternal; +import org.gradle.internal.logging.progress.ProgressLogger; +import org.gradle.internal.logging.progress.ProgressLoggerFactory; + +public class ThreadedProgressLoggerConsumer implements Consumer<String>, AutoCloseable { + public static final String CLOSE_LOGGERS = "LOOM_CLOSE_LOGGERS"; + + private final Project project; + private final String name; + private final String desc; + + private final ProgressLoggerFactory progressLoggerFactory; + private final ProgressLogger progressGroup; + private final Map<String, ProgressLogger> loggers = Collections.synchronizedMap(new HashMap<>()); + + public ThreadedProgressLoggerConsumer(Project project, String name, String desc) { + this.project = project; + this.name = name; + this.desc = desc; + + this.progressLoggerFactory = ((ProjectInternal) project).getServices().get(ProgressLoggerFactory.class); + this.progressGroup = this.progressLoggerFactory.newOperation(name).setDescription(desc); + progressGroup.started(); + } + + @Override + public void accept(String line) { + if (!line.contains("::")) { + project.getLogger().debug("Malformed threaded IPC log message: " + line); + return; + } + + int idx = line.indexOf("::"); + String id = line.substring(0, idx).trim(); + String data = line.substring(idx + 2).trim(); + + if (data.equals(CLOSE_LOGGERS)) { + resetLoggers(); + return; + } + + loggers.computeIfAbsent(id, this::createLogger).progress(data); + } + + private ProgressLogger createLogger(String id) { + ProgressLogger progressLogger = progressLoggerFactory.newOperation(getClass(), progressGroup); + progressLogger.setDescription(desc); + progressLogger.started(); + return progressLogger; + } + + private void resetLoggers() { + loggers.values().forEach(ProgressLogger::completed); + loggers.clear(); + } + + @Override + public void close() { + resetLoggers(); + + progressGroup.completed(); + } +} diff --git a/src/main/java/net/fabricmc/loom/util/gradle/ThreadedSimpleProgressLogger.java b/src/main/java/net/fabricmc/loom/util/gradle/ThreadedSimpleProgressLogger.java new file mode 100644 index 00000000..605568a9 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/gradle/ThreadedSimpleProgressLogger.java @@ -0,0 +1,36 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util.gradle; + +import java.io.IOException; + +import net.fabricmc.loom.util.IOStringConsumer; + +public record ThreadedSimpleProgressLogger(IOStringConsumer parent) implements IOStringConsumer { + @Override + public void accept(String data) throws IOException { + parent.accept("%d::%s".formatted(Thread.currentThread().getId(), data)); + } +} diff --git a/src/main/java/net/fabricmc/loom/util/gradle/WorkerDaemonClientsManagerHelper.java b/src/main/java/net/fabricmc/loom/util/gradle/WorkerDaemonClientsManagerHelper.java new file mode 100644 index 00000000..b5d1f7f1 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/gradle/WorkerDaemonClientsManagerHelper.java @@ -0,0 +1,77 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util.gradle; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.gradle.api.Transformer; +import org.gradle.workers.internal.DaemonForkOptions; +import org.gradle.workers.internal.WorkerDaemonClientsManager; + +public class WorkerDaemonClientsManagerHelper { + public static final String MARKER_PROP = "fabric.loom.decompile.worker"; + + public static boolean stopIdleJVM(WorkerDaemonClientsManager manager, String jvmMarkerValue) { + AtomicBoolean stopped = new AtomicBoolean(false); + + /* Transformer<List<WorkerDaemonClient>, List<WorkerDaemonClient>> */ + Transformer<List<Object>, List<Object>> transformer = workerDaemonClients -> { + for (Object /* WorkerDaemonClient */ client : workerDaemonClients) { + DaemonForkOptions forkOptions = getForkOptions(client); + Map<String, Object> systemProperties = forkOptions.getJavaForkOptions().getSystemProperties(); + + if (systemProperties == null || !jvmMarkerValue.equals(systemProperties.get(MARKER_PROP))) { + // Not the JVM we are looking for + continue; + } + + stopped.set(true); + return Collections.singletonList(client); + } + + return Collections.emptyList(); + }; + + //noinspection unchecked + manager.selectIdleClientsToStop((Transformer) transformer); + + return stopped.get(); + } + + private static DaemonForkOptions getForkOptions(Object /* WorkerDaemonClient */ client) { + try { + Method getForkOptionsMethod = client.getClass().getDeclaredMethod("getForkOptions"); + getForkOptionsMethod.setAccessible(true); + return (DaemonForkOptions) getForkOptionsMethod.invoke(client); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/util/ipc/IPCClient.java b/src/main/java/net/fabricmc/loom/util/ipc/IPCClient.java new file mode 100644 index 00000000..3e5563d0 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/ipc/IPCClient.java @@ -0,0 +1,67 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util.ipc; + +import java.io.IOException; +import java.net.UnixDomainSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; + +import net.fabricmc.loom.util.IOStringConsumer; + +public final class IPCClient implements IOStringConsumer, AutoCloseable { + private final Path path; + private final SocketChannel socketChannel; + + public IPCClient(Path path) throws IOException { + this.path = path; + socketChannel = setupChannel(); + } + + private SocketChannel setupChannel() throws IOException { + final UnixDomainSocketAddress address = UnixDomainSocketAddress.of(path); + return SocketChannel.open(address); + } + + @Override + public void accept(String s) throws IOException { + synchronized (socketChannel) { + ByteBuffer buf = ByteBuffer.wrap((s + "\n").getBytes(StandardCharsets.UTF_8)); + + while (buf.hasRemaining()) { + socketChannel.write(buf); + } + } + } + + @Override + public void close() throws Exception { + synchronized (socketChannel) { + socketChannel.close(); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/util/ipc/IPCServer.java b/src/main/java/net/fabricmc/loom/util/ipc/IPCServer.java new file mode 100644 index 00000000..7c8158a8 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/ipc/IPCServer.java @@ -0,0 +1,88 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util.ipc; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.StandardProtocolFamily; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.Scanner; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class IPCServer implements AutoCloseable { + private final ExecutorService loggerReceiverService = Executors.newSingleThreadExecutor(); + private final Path path; + private final Consumer<String> consumer; + + private final CountDownLatch startupLock = new CountDownLatch(1); + + public IPCServer(Path path, Consumer<String> consumer) { + this.path = path; + this.consumer = consumer; + + loggerReceiverService.submit(this::run); + + try { + startupLock.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException("Timed out waiting for IPC server thread to start", e); + } + } + + public void run() { + UnixDomainSocketAddress address = UnixDomainSocketAddress.of(path); + + try (ServerSocketChannel serverChannel = ServerSocketChannel.open(StandardProtocolFamily.UNIX)) { + serverChannel.bind(address); + + startupLock.countDown(); + + try (SocketChannel clientChannel = serverChannel.accept(); + Scanner scanner = new Scanner(clientChannel, StandardCharsets.UTF_8)) { + while (!Thread.currentThread().isInterrupted()) { + if (scanner.hasNextLine()) { + this.consumer.accept(scanner.nextLine()); + } + } + } + } catch (IOException e) { + throw new UncheckedIOException("Failed to listen for IPC messages", e); + } + } + + @Override + public void close() throws InterruptedException { + loggerReceiverService.shutdownNow(); + loggerReceiverService.awaitTermination(10, TimeUnit.SECONDS); + } +} |