JDK-8157913 : Launcher can not find path to libpackager.so
  • Type: Bug
  • Component: deploy
  • Sub-Component: packager
  • Affected Version: 8u92
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64
  • Submitted: 2016-05-10
  • Updated: 2018-10-29
  • Resolved: 2016-12-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u201Fixed 9Fixed
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)


However, this is irrelevant, as bug is caused by C++ code before JVM ist even started.

ADDITIONAL OS VERSION INFORMATION :
Linux 3.19.0-32-generic (amd64)

EXTRA RELEVANT SYSTEM CONFIGURATION :
Linux is _not_ running in a VM. Apparently freshly allocated memory on some VMs is pre-initialized to NULL bytes.

A DESCRIPTION OF THE PROBLEM :
The Linux launcher (http://hg.openjdk.java.net/openjfx/8u-dev/rt/file/922957ec457e/modules/fxpackager/src/main/native/launcher/linux/launcher.cpp) determines its own path by invoking:

  readlink("/proc/self/exe", buffer, MAX_PATH - 1)

However the c string created from this buffer is not correctly terminated, thus random contents from the buffer will become part of the path:

  buffer[MAX_PATH - 1] = '\0';

The correct position to append the NULL byte (i.e. the string length) would be returned by readlink, however this return value is not stored.

An example for correct usage is given in the readlink manpages (http://linux.die.net/man/3/readlink):

  ssizet_t len;
  if ((len = readlink("/modules/pass1", buf, sizeof(buf)-1)) != -1)
      buf[len] = '\0';

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Start launcher binary, that has been created by the JavaFX Packager.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Launcher can find libpackager.so and starts the JavaFX application.
ACTUAL -
Launcher can not find libpackager.so, as it searches in the wrong path.

Instead of "/opt/ApplicationName/libpackager.so" there are additional random characters appended after "/opt/ApplicationName/".

A concrete example is available on https://github.com/cryptomator/cryptomator/issues/265

ERROR MESSAGES/STACK TRACES THAT OCCUR :
/opt/Cryptomator/Cryptomatorn/libpackager.so not found.

REPRODUCIBILITY :
This bug can be reproduced often.

CUSTOMER SUBMITTED WORKAROUND :
Unpack packager-created packages, replace launcher by custom implementation, repackage manually.


Comments
+1 Approved to push to 8u-dev for 8u202.
25-10-2018

http://cr.openjdk.java.net/~almatvee/8157913/webrev.00/
23-10-2018

We should consider a backport to 8u-dev.
18-10-2018

Changeset: http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/9c4855540239
21-12-2016

+1
21-12-2016

That's right, I missed that. Actually we already do memset(,0,size) for the content of DynamicBuffer (in its constructor), so the problem should not appear in that part of code, but anyway we need to use readlink() properly. I'll create new webrev. And I'll push it to the sandbox.
20-12-2016

New webrev: http://cr.openjdk.java.net/~vdrozdov/JDK-8157913/webrev.01/
20-12-2016

LinuxPlatform.cpp should also be addressed: TString LinuxPlatform::GetModuleFileName() { TString result; DynamicBuffer<TCHAR> buffer(MAX_PATH); if (readlink("/proc/self/exe", buffer.GetData(), MAX_PATH - 1) != -1) { result = buffer.GetData(); } return result; } unless it isn't a problem?
19-12-2016

Webrev: http://cr.openjdk.java.net/~vdrozdov/JDK-8157913/webrev.00/
19-12-2016

I think we can do following: 1) We can use "char buffer[MAX_PATH] = {0}", to prevent any problems with initialization. No need to use new/delete here. 2) Use this function according to docs specification: RETURN VALUE Upon successful completion, readlink() shall return the count of bytes placed in the buffer. Otherwise, it shall return a value of -1, leave the buffer unchanged, and set errno to indicate the error. ... EXAMPLES Reading the Name of a Symbolic Link char buf[1024]; ssizet_t len; ... if ((len = readlink("/modules/pass1", buf, sizeof(buf)-1)) != -1) buf[len] = '\0';
15-12-2016