Hi Xu,
Thank you for contributing the patch! It looks reasonable. If you don't
have access to the JBS, you may use [1] to submit your bug report.
[1] https://bugreport.java.com/bugreport/
- Alexey
On 3/11/2026 5:27 AM, Xu Jiawei wrote:
Hello core-libs-dev,
While packaging an app with jpackage on Linux, I encountered a
reproducible SIGSEGV when the input directory contains a large number of
JAR files (e.g. 1000 or more). A reproducer Makefile is included below.
If the Makefile does not reproduce the failure on a particular system,
increasing `JAR_COUNT` may trigger it.
After investigation, it appears the launcher assumes that `read()` and
`write()` on the pipe between parent and child transfer the full
requested size in a single call. However, when the serialized
`JvmlLauncherData` buffer becomes large (about 100KB in my test), the
parent may receive only a partial read.
For example (strace excerpt):
- Child write: returns 16384 when 102028 was requested.
- Parent read: returns 8192 when 102028 was requested.
```
06:42:45.145883 write(4,
"h\212\352\252#V\0\0\6\0\0\0\2\0\0\0\310\212\352\252#V\0\08\30\354\252#V\0\0"...,
102028) = 16384
06:42:45.146017 read(3,
"h\212\352\252#V\0\0\6\0\0\0\2\0\0\0\310\212\352\252#V\0\08\30\354\252#V\0\0"...,
102028) = 8192
```
Neither the parent nor the child loops to transfer the remaining bytes.
This results in a truncated configuration buffer, and the launcher
subsequently crashes in `jvmLauncherStartJvm()` (observed in
`__setenv()`). As POSIX permits partial transfers on pipes, especially
for buffers larger than the pipe capacity, the current implementation
appears to assume that transfers complete the full transfer in a single
call, which may not always hold.
I have prepared a patch that introduces static `readFully()` and
`writeFully()` functions to ensure complete buffer transfer, and I've
verified it resolves the crash. While I also noticed a similar pair of
functions exists in `src/java.base/unix/native/libjava/childproc.c`, I
opted for a local static function to avoid unnecessary linking across
modules. The proposed change is available here:
https://github.com/sseu-buhzzi/jdk/commit/e78c0ec0a02eec92cad7f9f34a1f6c82970522cc
I do not currently have JBS access. If appropriate, could someone please
create a JBS issue for this (or advise on the correct process)? I can
then submit the patch for formal review.
Best regards,
Xu Jiawei
---- Reproducer Makefile ----
JAVA_HOME ?= $(shell which javac | xargs realpath | sed 's:/bin/javac::')
JAVAC = $(JAVA_HOME)/bin/javac
JAR = $(JAVA_HOME)/bin/jar
JPACKAGE = $(JAVA_HOME)/bin/jpackage
APP_NAME = LongCp
JAR_COUNT ?= 1024
LIBS_DIR = libs
OUTPUT_DIR = output
LAUNCHER = $(OUTPUT_DIR)/$(APP_NAME)/bin/$(APP_NAME)
define MAIN_JAVA_CONTENT
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
endef
export MAIN_JAVA_CONTENT
all: run
clean:
rm -rf Main.java Main.class $(LIBS_DIR) $(OUTPUT_DIR)
run: $(LAUNCHER)
$(LAUNCHER) || echo 'Bug.'
$(LAUNCHER): $(LIBS_DIR)/main.jar
rm -rf $(OUTPUT_DIR)
$(JPACKAGE) --type app-image \
--name $(APP_NAME) \
--input $(LIBS_DIR) \
--main-jar main.jar \
--main-class Main \
--dest $(OUTPUT_DIR)
$(LIBS_DIR)/main.jar: Main.class $(LIBS_DIR)
$(JAR) cf $(LIBS_DIR)/main.jar Main.class
Main.class: Main.java
$(JAVAC) Main.java
Main.java:
printf '%s' "$$MAIN_JAVA_CONTENT" > Main.java
$(LIBS_DIR):
mkdir -p $(LIBS_DIR)
seq -f '$(LIBS_DIR)/dummy-%010g.jar' 1 $(JAR_COUNT) | xargs touch