test/hotspot/jtreg/runtime/ThreadSignalMask/exeThreadSignalMask.c
author ssahoo
Wed, 04 Jul 2018 03:44:32 -0700
changeset 50936 00b16d0457e4
parent 47216 71c04702a3d5
permissions -rw-r--r--
8205653: test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java and RmiSslBootstrapTest.sh fail with handshake_failure Summary: Test failure due to unsupported DSA keys Reviewed-by: dfuchs, xuelei

/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#define _POSIX_PTHREAD_SEMANTICS // to enable POSIX semantics for certain common APIs

#include <jni.h>
#include <dlfcn.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void *handle;
char *error;
char path[PATH_MAX];

jint(JNICALL *jni_create_java_vm)(JavaVM **, JNIEnv **, void *) = NULL;

JavaVM *jvm;

// method to perform dlclose on an open dynamic library handle
void closeHandle() {
  dlclose(handle);
  if ((error = dlerror()) != NULL) {
    fputs("Error occurred while closing handle\n", stderr);
  }
}

// method to exit with a fail status
void fail() {
  if (handle) {
    closeHandle();
  }
  exit(1);
}

// method to handle occurred error and fail
void handleError(char *messageTitle, char *messageBody) {
  fprintf(stderr, "%s: %s\n", messageTitle, messageBody);
  fail();
}

// method to load the dynamic library libjvm
void loadJVM() {
  char lib[PATH_MAX];
  snprintf(lib, sizeof (lib), "%s/lib/server/libjvm.so", path);
  handle = dlopen(lib, RTLD_LAZY);
  if (!handle) {
    handleError(dlerror(), "2");
  }
  fputs("Will load JVM...\n", stdout);

  // find the address of function
  *(void **) (&jni_create_java_vm) = dlsym(handle, "JNI_CreateJavaVM");
  if ((error = dlerror()) != NULL) {
    handleError(error, "3");
  }

  fputs("JVM loaded okay.\n", stdout);
}

// method to get created jvm environment
JNIEnv* initJVM() {
  JNIEnv *env = NULL;
  JavaVMInitArgs vm_args;
  JavaVMOption options[1];
  jint res;

  options[0].optionString = "-Xrs";

  vm_args.version = JNI_VERSION_1_2;
  vm_args.nOptions = 1;
  vm_args.options = options;
  vm_args.ignoreUnrecognized = JNI_FALSE;

  fputs("Will create JVM...\n", stdout);

  res = (*jni_create_java_vm)(&jvm, &env, &vm_args);
  if (res < 0) {
    handleError("Can't create Java VM", strerror(res));
  }

  fputs("JVM created OK!\n", stdout);
  return env;
}

// method to invoke java method from java class
void callJava(JNIEnv *env) {
  jclass cls;
  jmethodID mid;
  jstring jstr;
  jobjectArray args;

  cls = (*env)->FindClass(env, "Prog");
  if (cls == 0) {
    handleError("FindClass", "Can't find Prog class");
  }

  mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
  if (mid == 0) {
    handleError("GetStaticMethodID", "Can't find Prog.main");
  }

  jstr = (*env)->NewStringUTF(env, "from C!");
  if (jstr == 0) {
    handleError("NewStringUTF", "Out of memory");
  }
  args = (*env)->NewObjectArray(env, 1,
          (*env)->FindClass(env, "java/lang/String"), jstr);
  if (args == 0) {
    handleError("NewObjectArray", "Out of memory");
  }
  (*env)->CallStaticVoidMethod(env, cls, mid, args);

}

// method to load, init jvm and then invoke java method
void* loadAndCallJava(void* x) {
  JNIEnv *env;

  fputs("Some thread will create JVM.\n", stdout);
  loadJVM();
  env = initJVM();

  fputs("Some thread will call Java.\n", stdout);

  callJava(env);

  if ((*jvm)->DetachCurrentThread(jvm) != 0)
    fputs("Error: thread not detached!\n", stderr);
  fputs("Some thread exiting.\n", stdout);
  return env;
}

int main(int argc, char **argv) {
  JNIEnv *env;
  sigset_t set;
  pthread_t thr1;
  pthread_attr_t attr;
  size_t ss = 0;
  int sig;
  int rc; // return code for pthread_* methods

  // verify input
  if (argc != 2) {
    handleError("usage", "a.out jdk_path");
  }
  // copy input jdk path into a char buffer
  strncpy(path, argv[1], PATH_MAX);
  // add null termination character
  path[PATH_MAX - 1] = '\0';

  fputs("Main thread will set signal mask.\n", stdout);

  // initialize the signal set
  sigemptyset(&set);
  // add a number of signals to a signal set
  sigaddset(&set, SIGPIPE);
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGHUP);
  sigaddset(&set, SIGINT);

  // examine and change mask of blocked signal
  if ((rc = pthread_sigmask(SIG_BLOCK, &set, NULL))) {
    // handle error if occurred
    handleError("main: pthread_sigmask() error", strerror(rc));
  }

  // initializes the thread attributes object with default attribute values
  if ((rc = pthread_attr_init(&attr))) {
    // handle error if occurred
    handleError("main: pthread_attr_init() error", strerror(rc));
  }

  ss = 1024 * 1024;
  // set the stack size attribute of the thread attributes object
  if ((rc = pthread_attr_setstacksize(&attr, ss))) {
    // handle error if occurred
    handleError("main: pthread_attr_setstacksize() error", strerror(rc));
  }
  // get the stack size attribute of the thread attributes object
  if ((rc = pthread_attr_getstacksize(&attr, &ss))) {
    // handle error if occurred
    handleError("main: pthread_attr_getstacksize() error", strerror(rc));
  }
  fprintf(stderr, "Stack size: %zu\n", ss);

  // start a new thread in the calling process,
  // loadAndCallJava logic is passed as a start_routine argument
  if ((rc = pthread_create(&thr1, NULL, loadAndCallJava, NULL))) {
    // handle error if occurred
    handleError("main: pthread_create() error", strerror(rc));
  }

  // initialize the signal set
  sigemptyset(&set);
  // add a number of signals to a signal set
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGHUP);
  sigaddset(&set, SIGINT);

  fputs("Main thread waiting for signal.\n", stdout);

  do {
    int err;

    sig = 0;
    err = sigwait(&set, &sig);
    if (err != 0) {
      // print error message if unexpected signal occurred
      fprintf(stderr, "main: sigwait() error:  %s\n", strerror(err));
    } else {
      // print success message and exit if expected signal occurred
      // this branch generally acts when JVM executes destroy()
      fprintf(stdout, "main: sigwait() got:  %d\nSucceed!\n", sig);
      exit(0);
    }
  } while (sig != SIGTERM && sig != SIGINT); // exit the loop condition

  // join with a terminated thread
  if ((rc = pthread_join(thr1, NULL))) {
    // handle error if occurred
    handleError("main: pthread_join() error", strerror(rc));
  }

  // close an open dynamic library handle
  closeHandle();
  fputs("Main thread exiting.\n", stdout);
  return 0;
}