[libbluray-devel] [PATCH 1/2] Get the correct java home on macOS

Petri Hintukainen phintuka at users.sourceforge.net
Fri Dec 9 14:31:12 CET 2016


to, 2016-12-08 kello 03:47 +0100, Marvin Scholz kirjoitti:
> 
> On macOS apparently the only way to get the correct
> path to the java home for the currently active SDK as
> selected by the user is to use the /usr/libexec/java_home
> tool.
> ---
> It turned out the previous patchset actually still did work fine in
> all cases, so this one does not use popen/pclose at all anymore,
> which hopefully works in all cases.
> 
> Additionally the check if JLI was loaded properly was done the other
> way around, so it would log that it was not able to load JLI when it
> actually was, which is fixed in this version of the second patch.
> 
>  src/libbluray/bdj/bdj.c | 89
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 89 insertions(+)
> 
> diff --git a/src/libbluray/bdj/bdj.c b/src/libbluray/bdj/bdj.c
> index d3d4c43..1a03be6 100644
> --- a/src/libbluray/bdj/bdj.c
> +++ b/src/libbluray/bdj/bdj.c
> @@ -39,6 +39,13 @@
>  #include <stdlib.h>
>  #include <string.h>
>  
> +#ifdef __APPLE__
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include <limits.h>
> +#include <unistd.h>
> +#endif
> +
>  #ifdef _WIN32
>  #include <windows.h>
>  #include <winreg.h>
> @@ -174,6 +181,75 @@ static inline char *_utf8_to_cp(const char
> *utf8)
>  }
>  #endif
>  
> +#if defined(__APPLE__) && !defined(HAVE_BDJ_J2ME)
> +
> +#define MACOS_JAVA_HOME "/usr/libexec/java_home"
> +static char *_java_home_macos()
> +{
> +    static char result[PATH_MAX] = "";
> +
> +    if (result[0])
> +        return result;
> +
> +    pid_t java_home_pid;
> +    int fd[2], exitcode;
> +
> +    if (pipe(fd)) {
> +        BD_DEBUG(DBG_BDJ | DBG_CRIT, "unable to set up pipes\n");
> +        return NULL;
> +    }
> +
> +    switch (java_home_pid = vfork())

I must say I don't like the idea of forking in library. But if there
are no other ways around the problem ... I don't like running Java VM
in library either :).

> 
> +    {
> +        case -1:
> +            BD_DEBUG(DBG_BDJ | DBG_CRIT, "vfork failed\n");
> +            return NULL;
> +
> +        case 0:
> +            if (dup2(fd[1], STDOUT_FILENO) == -1) {
> +                BD_DEBUG(DBG_BDJ | DBG_CRIT, "unable to dup2
> fd[1]\n");

You can't log anything here. It may deadlock or clobber parent process
state. If you want to log child process errors you need to signal the
error with _exit() and log the message in the parent process.

> 
> +                exit(-1);

Should this be _exit() ?

man vfork:
"(From POSIX.1) The vfork() function has the same effect as fork(2),
except that the behavior is undefined if the process created by vfork()
either modifies any data other than a variable of type pid_t used to
store the return value from vfork(), or returns from the function in
which vfork() was called, or calls any other function before
successfully calling _exit(2) or one of the exec(3) family of
functions."

> 
> +            }
> +
> +            close(fd[1]);
> +            close(fd[0]);
> +
> +            execl(MACOS_JAVA_HOME, MACOS_JAVA_HOME);
> +
> +            BD_DEBUG(DBG_BDJ | DBG_CRIT,
> +                     "unable to execute " MACOS_JAVA_HOME "\n");
> +
> +            exit(-1);
> +
> +        default:
> +            close(fd[1]);
> +
> +            for (int len = 0; ;) {
> +                int n = read(fd[0], result + len, sizeof result -
> len);
> +                if (n <= 0)
> +                    break;
> +
> +                len += n;
> +                result[len-1] = '\0';
> +            }
> +
> +            waitpid(java_home_pid, &exitcode, 0);
> +    }
> +
> +    if (result[0] == '\0' || exitcode) {
> +        BD_DEBUG(DBG_BDJ | DBG_CRIT,
> +                 "Unable to read path from " MACOS_JAVA_HOME "\n");
> +        result[0] = '\0';
> +        return NULL;
> +    }
> +
> +    BD_DEBUG(DBG_BDJ, "macos java home: '%s'\n", result );
> +    return result;
> +}
> +#undef MACOS_JAVA_HOME
> +
> +#endif
> +
>  static void *_jvm_dlopen(const char *java_home, const char *jvm_dir,
> const char *jvm_lib)
>  {
>      if (java_home) {
> @@ -210,6 +286,10 @@ static void *_load_jvm(const char **p_java_home)
>      static const char  jvm_dir[]  = "jre\\bin\\server";
>      static const char  jvm_lib[]  = "jvm";
>  # else
> +#  ifdef __APPLE__
> +    static const char *jvm_path[] = {NULL, JDK_HOME};
> +    static const char  jvm_dir[]  = "jre/lib/server";
> +#  else
>      static const char *jvm_path[] = {NULL, JDK_HOME,
>                                       "/usr/lib/jvm/default-java",
>                                       "/usr/lib/jvm/default",
> @@ -220,6 +300,7 @@ static void *_load_jvm(const char **p_java_home)
>                                       "/usr/lib/jvm/java-6-openjdk",
>      };
>      static const char  jvm_dir[]  = "jre/lib/" JAVA_ARCH "/server";
> +#  endif
>      static const char  jvm_lib[]  = "libjvm";
>  # endif
>  #endif
> @@ -241,6 +322,14 @@ static void *_load_jvm(const char **p_java_home)
>      }
>  #endif
>  
> +#if defined(__APPLE__) && !defined(HAVE_BDJ_J2ME)
> +    java_home = _java_home_macos();
> +    if (java_home) {
> +        *p_java_home = java_home;
> +        return _jvm_dlopen(java_home, jvm_dir, jvm_lib);
> +    }
> +#endif
> +
>      BD_DEBUG(DBG_BDJ, "JAVA_HOME not set, trying default
> locations\n");
>  
>      /* try our pre-defined locations */


More information about the libbluray-devel mailing list