--- old/make/lib/Lib-jdk.hotspot.agent.gmk 2019-01-10 19:12:51.958240442 +0900 +++ new/make/lib/Lib-jdk.hotspot.agent.gmk 2019-01-10 19:12:51.750242330 +0900 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2019, 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 @@ -66,7 +66,7 @@ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \ EXTRA_SRC := $(LIBSA_EXTRA_SRC), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS), \ - LIBS_linux := -lthread_db $(LIBDL), \ + LIBS_linux := $(LIBDL), \ LIBS_solaris := -ldl -ldemangle -lthread -lproc, \ LIBS_macosx := -framework Foundation -framework JavaNativeFoundation \ -framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \ --- old/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c 2019-01-10 19:12:52.428236175 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c 2019-01-10 19:12:52.218238081 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, 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 @@ -24,6 +24,7 @@ #include #include "libproc.h" +#include "proc_service.h" #include #include @@ -241,10 +242,10 @@ /* * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal * Method: attach0 - * Signature: (IZ)V + * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__IZ - (JNIEnv *env, jobject this_obj, jint jpid, jboolean is_in_container) { +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I + (JNIEnv *env, jobject this_obj, jint jpid) { // For bitness checking, locate binary at /proc/jpid/exe char buf[PATH_MAX]; @@ -254,7 +255,7 @@ char err_buf[200]; struct ps_prochandle* ph; - if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf), is_in_container)) == NULL) { + if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) { char msg[230]; snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf); THROW_NEW_DEBUGGER_EXCEPTION(msg); --- old/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h 2019-01-10 19:12:52.906231835 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h 2019-01-10 19:12:52.702233687 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, 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 @@ -28,41 +28,10 @@ #include #include #include -#include "proc_service.h" +#include #include -/************************************************************************************ - -0. This is very minimal subset of Solaris libproc just enough for current application. -Please note that the bulk of the functionality is from proc_service interface. This -adds Pgrab__ and some missing stuff. We hide the difference b/w live process and core -file by this interface. - -1. pthread_id unique in both NPTL & LinuxThreads. We store this in -OSThread::_pthread_id in JVM code. - -2. All threads see the same pid when they call getpid() under NPTL. -Threads receive different pid under LinuxThreads. We used to save the result of -::getpid() call in OSThread::_thread_id. This way uniqueness of OSThread::_thread_id -was lost under NPTL. Now, we store the result of ::gettid() call in -OSThread::_thread_id. Because gettid returns actual pid of thread (lwp id), this is -unique again. We therefore use OSThread::_thread_id as unique identifier. - -3. There is a unique LWP id under both thread libraries. libthread_db maps pthread_id -to its underlying lwp_id under both the thread libraries. thread_info.lwp_id stores -lwp_id of the thread. The lwp id is nothing but the actual pid of clone'd processes. But -unfortunately libthread_db does not work very well for core dumps. So, we get pthread_id -only for processes. For core dumps, we don't use libthread_db at all (like gdb). - -4. ptrace operates on this LWP id under both the thread libraries. When we say 'pid' for -ptrace call, we refer to lwp_id of the thread. - -5. for core file, we parse ELF files and read data from them. For processes we use -combination of ptrace and /proc calls. - -*************************************************************************************/ - #if defined(sparc) || defined(sparcv9) || defined(ppc64) || defined(ppc64le) #include @@ -87,7 +56,7 @@ // attach to a process JNIEXPORT struct ps_prochandle* JNICALL -Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container); +Pgrab(pid_t pid, char* err_buf, size_t err_buf_len); // attach to a core dump JNIEXPORT struct ps_prochandle* JNICALL --- old/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c 2019-01-10 19:12:53.380227532 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c 2019-01-10 19:12:53.178229366 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, 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 @@ -26,8 +26,9 @@ #include #include #include -#include +#include #include "libproc_impl.h" +#include "proc_service.h" #define SA_ALTROOT "SA_ALTROOT" @@ -116,13 +117,6 @@ init_libproc(bool debug) { // init debug mode _libsaproc_debug = debug; - - // initialize the thread_db library - if (td_init() != TD_OK) { - print_debug("libthread_db's td_init failed\n"); - return false; - } - return true; } @@ -256,7 +250,7 @@ } // add a thread to ps_prochandle -thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { +thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) { thread_info* newthr; if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) { print_debug("can't allocate memory for thread_info\n"); @@ -264,7 +258,6 @@ } // initialize thread info - newthr->pthread_id = pthread_id; newthr->lwp_id = lwp_id; // add new thread to the list @@ -295,64 +288,6 @@ free(current_thr); } -// struct used for client data from thread_db callback -struct thread_db_client_data { - struct ps_prochandle* ph; - thread_info_callback callback; -}; - -// callback function for libthread_db -static int thread_db_callback(const td_thrhandle_t *th_p, void *data) { - struct thread_db_client_data* ptr = (struct thread_db_client_data*) data; - td_thrinfo_t ti; - td_err_e err; - - memset(&ti, 0, sizeof(ti)); - err = td_thr_get_info(th_p, &ti); - if (err != TD_OK) { - print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n"); - return err; - } - - print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid); - - if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) { - print_debug("Skipping pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid); - return TD_OK; - } - - if (ptr->callback(ptr->ph, ti.ti_tid, ti.ti_lid) != true) - return TD_ERR; - - return TD_OK; -} - -// read thread_info using libthread_db -bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) { - struct thread_db_client_data mydata; - td_thragent_t* thread_agent = NULL; - if (td_ta_new(ph, &thread_agent) != TD_OK) { - print_debug("can't create libthread_db agent\n"); - return false; - } - - mydata.ph = ph; - mydata.callback = cb; - - // we use libthread_db iterator to iterate thru list of threads. - if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata, - TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, - TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) { - td_ta_delete(thread_agent); - return false; - } - - // delete thread agent - td_ta_delete(thread_agent); - return true; -} - - // get number of threads int get_num_threads(struct ps_prochandle* ph) { return ph->num_threads; @@ -484,7 +419,6 @@ return PS_OK; } -// new libthread_db of NPTL seem to require this symbol JNIEXPORT ps_err_e JNICALL ps_get_thread_area() { print_debug("ps_get_thread_area not implemented\n"); --- old/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h 2019-01-10 19:12:53.869223093 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h 2019-01-10 19:12:53.638225190 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, 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 @@ -46,7 +46,6 @@ // list of threads typedef struct thread_info { lwpid_t lwp_id; - pthread_t pthread_id; // not used cores, always -1 struct user_regs_struct regs; // not for process, core uses for caching regset struct thread_info* next; } thread_info; @@ -108,11 +107,6 @@ void print_error(const char* format,...); bool is_debug(); -typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid); - -// reads thread info using libthread_db and calls above callback for each thread -bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb); - // deletes a thread from the thread list void delete_thread_info(struct ps_prochandle* ph, thread_info* thr); @@ -124,7 +118,7 @@ uintptr_t base); // adds a new thread to threads list, returns NULL on failure -thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id); +thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id); // a test for ELF signature without using libelf bool is_elf_file(int fd); --- old/src/jdk.hotspot.agent/linux/native/libsaproc/proc_service.h 2019-01-10 19:12:54.351218717 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/proc_service.h 2019-01-10 19:12:54.142220615 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, 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 @@ -26,12 +26,10 @@ #define _PROC_SERVICE_H_ #include -#include +#include #include "jni.h" +#include "libproc.h" -// Linux does not have the proc service library, though it does provide the -// thread_db library which can be used to manipulate threads without having -// to know the details of NPTL // copied from Solaris "proc_service.h" typedef enum { @@ -79,7 +77,6 @@ JNIEXPORT ps_err_e JNICALL ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset); -// new libthread_db of NPTL seem to require this symbol JNIEXPORT ps_err_e JNICALL ps_get_thread_area(); --- old/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c 2019-01-10 19:12:54.820214460 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c 2019-01-10 19:12:54.607216393 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, 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 @@ -31,6 +31,7 @@ #include #include #include "libproc_impl.h" +#include "proc_service.h" #include "salibelf.h" #include "cds.h" @@ -510,8 +511,7 @@ prstatus_t* prstat = (prstatus_t*) buf; thread_info* newthr; print_debug("got integer regset for lwp %d\n", prstat->pr_pid); - // we set pthread_t to -1 for core dump - if((newthr = add_thread_info(ph, (pthread_t) -1, prstat->pr_pid)) == NULL) + if((newthr = add_thread_info(ph, prstat->pr_pid)) == NULL) return false; // copy regs --- old/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c 2019-01-10 19:12:55.313209984 +0900 +++ new/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c 2019-01-10 19:12:55.084212063 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, 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 @@ -339,11 +339,6 @@ return rslt; } -// callback for read_thread_info -static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { - return add_thread_info(ph, pthread_id, lwp_id) != NULL; -} - static bool read_lib_info(struct ps_prochandle* ph) { char fname[32]; char buf[PATH_MAX]; @@ -443,7 +438,7 @@ // attach to the process. One and only one exposed stuff JNIEXPORT struct ps_prochandle* JNICALL -Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) { +Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) { struct ps_prochandle* ph = NULL; thread_info* thr = NULL; attach_state_t attach_status = ATTACH_SUCCESS; @@ -464,6 +459,7 @@ // initialize ps_prochandle ph->pid = pid; + add_thread_info(ph, ph->pid); // initialize vtable ph->ops = &process_ops; @@ -473,33 +469,30 @@ // the list of threads within the same process. read_lib_info(ph); - // read thread info - if (is_in_container) { - /* - * If the process is running in the container, SA scans all tasks in - * /proc//task to read all threads info. - */ - char taskpath[PATH_MAX]; - DIR *dirp; - struct dirent *entry; - - snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid); - dirp = opendir(taskpath); - int lwp_id; - while ((entry = readdir(dirp)) != NULL) { - if (*entry->d_name == '.') { - continue; - } - lwp_id = atoi(entry->d_name); - if (lwp_id == ph->pid) { - continue; - } - add_new_thread(ph, -1, lwp_id); + /* + * Read thread info. + * SA scans all tasks in /proc//task to read all threads info. + */ + char taskpath[PATH_MAX]; + DIR *dirp; + struct dirent *entry; + + snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid); + dirp = opendir(taskpath); + int lwp_id; + while ((entry = readdir(dirp)) != NULL) { + if (*entry->d_name == '.') { + continue; + } + lwp_id = atoi(entry->d_name); + if (lwp_id == ph->pid) { + continue; + } + if (!process_doesnt_exist(lwp_id)) { + add_thread_info(ph, lwp_id); } - closedir(dirp); - } else { - read_thread_info(ph, add_new_thread); } + closedir(dirp); // attach to the threads thr = ph->threads; --- old/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java 2019-01-10 19:12:55.813205445 +0900 +++ new/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java 2019-01-10 19:12:55.602207360 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, 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 @@ -102,7 +102,7 @@ private native static void init0() throws DebuggerException; private native void setSAAltRoot0(String altroot); - private native void attach0(int pid, boolean isInContainer) + private native void attach0(int pid) throws DebuggerException; private native void attach0(String execName, String coreName) throws DebuggerException; @@ -321,9 +321,8 @@ class AttachTask implements WorkerThreadTask { int pid; - boolean isInContainer; public void doit(LinuxDebuggerLocal debugger) { - debugger.attach0(pid, isInContainer); + debugger.attach0(pid); debugger.attached = true; debugger.isCore = false; findABIVersion(); @@ -332,7 +331,6 @@ AttachTask task = new AttachTask(); task.pid = processID; - task.isInContainer = (processID != NSpid); workerThread.execute(task); }