< prev index next >

src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c

Print this page


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


 322      while(*str&&*str!=delim) str++;
 323      while(*str&&*str==delim) *(str++) = new_delim;
 324    }
 325 
 326    return i;
 327 }
 328 
 329 /*
 330  * fgets without storing '\n' at the end of the string
 331  */
 332 static char * fgets_no_cr(char * buf, int n, FILE *fp)
 333 {
 334    char * rslt = fgets(buf, n, fp);
 335    if (rslt && buf && *buf){
 336        char *p = strchr(buf, '\0');
 337        if (*--p=='\n') *p='\0';
 338    }
 339    return rslt;
 340 }
 341 
 342 // callback for read_thread_info
 343 static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
 344   return add_thread_info(ph, pthread_id, lwp_id) != NULL;
 345 }
 346 
 347 static bool read_lib_info(struct ps_prochandle* ph) {
 348   char fname[32];
 349   char buf[PATH_MAX];
 350   FILE *fp = NULL;
 351 
 352   sprintf(fname, "/proc/%d/maps", ph->pid);
 353   fp = fopen(fname, "r");
 354   if (fp == NULL) {
 355     print_debug("can't open /proc/%d/maps file\n", ph->pid);
 356     return false;
 357   }
 358 
 359   while(fgets_no_cr(buf, PATH_MAX, fp)){
 360     char * word[7];
 361     int nwords = split_n_str(buf, 7, word, ' ', '\0');
 362 
 363     if (nwords < 6) {
 364       // not a shared library entry. ignore.
 365       continue;
 366     }


 426   thread_info* thr = ph->threads;
 427   while (thr) {
 428      ptrace_detach(thr->lwp_id);
 429      thr = thr->next;
 430   }
 431 }
 432 
 433 static void process_cleanup(struct ps_prochandle* ph) {
 434   detach_all_pids(ph);
 435 }
 436 
 437 static ps_prochandle_ops process_ops = {
 438   .release=  process_cleanup,
 439   .p_pread=  process_read_data,
 440   .p_pwrite= process_write_data,
 441   .get_lwp_regs= process_get_lwp_regs
 442 };
 443 
 444 // attach to the process. One and only one exposed stuff
 445 JNIEXPORT struct ps_prochandle* JNICALL
 446 Pgrab(pid_t pid, char* err_buf, size_t err_buf_len, bool is_in_container) {
 447   struct ps_prochandle* ph = NULL;
 448   thread_info* thr = NULL;
 449   attach_state_t attach_status = ATTACH_SUCCESS;
 450 
 451   if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
 452     snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
 453     print_debug("%s\n", err_buf);
 454     return NULL;
 455   }
 456 
 457   if ((attach_status = ptrace_attach(pid, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
 458     if (attach_status == ATTACH_THREAD_DEAD) {
 459        print_error("The process with pid %d does not exist.\n", pid);
 460     }
 461     free(ph);
 462     return NULL;
 463   }
 464 
 465   // initialize ps_prochandle
 466   ph->pid = pid;

 467 
 468   // initialize vtable
 469   ph->ops = &process_ops;
 470 
 471   // read library info and symbol tables, must do this before attaching threads,
 472   // as the symbols in the pthread library will be used to figure out
 473   // the list of threads within the same process.
 474   read_lib_info(ph);
 475 
 476   // read thread info
 477   if (is_in_container) {
 478     /*
 479      * If the process is running in the container, SA scans all tasks in
 480      * /proc/<PID>/task to read all threads info.
 481      */
 482     char taskpath[PATH_MAX];
 483     DIR *dirp;
 484     struct dirent *entry;
 485 
 486     snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid);
 487     dirp = opendir(taskpath);
 488     int lwp_id;
 489     while ((entry = readdir(dirp)) != NULL) {
 490       if (*entry->d_name == '.') {
 491         continue;
 492       }
 493       lwp_id = atoi(entry->d_name);
 494       if (lwp_id == ph->pid) {
 495         continue;
 496       }
 497       add_new_thread(ph, -1, lwp_id);

 498     }
 499     closedir(dirp);
 500   } else {
 501     read_thread_info(ph, add_new_thread);
 502   }

 503 
 504   // attach to the threads
 505   thr = ph->threads;
 506 
 507   while (thr) {
 508     thread_info* current_thr = thr;
 509     thr = thr->next;
 510     // don't attach to the main thread again
 511     if (ph->pid != current_thr->lwp_id) {
 512       if ((attach_status = ptrace_attach(current_thr->lwp_id, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
 513         if (attach_status == ATTACH_THREAD_DEAD) {
 514           // Remove this thread from the threads list
 515           delete_thread_info(ph, current_thr);
 516         }
 517         else {
 518           Prelease(ph);
 519           return NULL;
 520         } // ATTACH_THREAD_DEAD
 521       } // !ATTACH_SUCCESS
 522     }
   1 /*
   2  * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 322      while(*str&&*str!=delim) str++;
 323      while(*str&&*str==delim) *(str++) = new_delim;
 324    }
 325 
 326    return i;
 327 }
 328 
 329 /*
 330  * fgets without storing '\n' at the end of the string
 331  */
 332 static char * fgets_no_cr(char * buf, int n, FILE *fp)
 333 {
 334    char * rslt = fgets(buf, n, fp);
 335    if (rslt && buf && *buf){
 336        char *p = strchr(buf, '\0');
 337        if (*--p=='\n') *p='\0';
 338    }
 339    return rslt;
 340 }
 341 





 342 static bool read_lib_info(struct ps_prochandle* ph) {
 343   char fname[32];
 344   char buf[PATH_MAX];
 345   FILE *fp = NULL;
 346 
 347   sprintf(fname, "/proc/%d/maps", ph->pid);
 348   fp = fopen(fname, "r");
 349   if (fp == NULL) {
 350     print_debug("can't open /proc/%d/maps file\n", ph->pid);
 351     return false;
 352   }
 353 
 354   while(fgets_no_cr(buf, PATH_MAX, fp)){
 355     char * word[7];
 356     int nwords = split_n_str(buf, 7, word, ' ', '\0');
 357 
 358     if (nwords < 6) {
 359       // not a shared library entry. ignore.
 360       continue;
 361     }


 421   thread_info* thr = ph->threads;
 422   while (thr) {
 423      ptrace_detach(thr->lwp_id);
 424      thr = thr->next;
 425   }
 426 }
 427 
 428 static void process_cleanup(struct ps_prochandle* ph) {
 429   detach_all_pids(ph);
 430 }
 431 
 432 static ps_prochandle_ops process_ops = {
 433   .release=  process_cleanup,
 434   .p_pread=  process_read_data,
 435   .p_pwrite= process_write_data,
 436   .get_lwp_regs= process_get_lwp_regs
 437 };
 438 
 439 // attach to the process. One and only one exposed stuff
 440 JNIEXPORT struct ps_prochandle* JNICALL
 441 Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
 442   struct ps_prochandle* ph = NULL;
 443   thread_info* thr = NULL;
 444   attach_state_t attach_status = ATTACH_SUCCESS;
 445 
 446   if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
 447     snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
 448     print_debug("%s\n", err_buf);
 449     return NULL;
 450   }
 451 
 452   if ((attach_status = ptrace_attach(pid, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
 453     if (attach_status == ATTACH_THREAD_DEAD) {
 454        print_error("The process with pid %d does not exist.\n", pid);
 455     }
 456     free(ph);
 457     return NULL;
 458   }
 459 
 460   // initialize ps_prochandle
 461   ph->pid = pid;
 462   add_thread_info(ph, ph->pid);
 463 
 464   // initialize vtable
 465   ph->ops = &process_ops;
 466 
 467   // read library info and symbol tables, must do this before attaching threads,
 468   // as the symbols in the pthread library will be used to figure out
 469   // the list of threads within the same process.
 470   read_lib_info(ph);
 471 


 472   /*
 473    * Read thread info.
 474    * SA scans all tasks in /proc/<PID>/task to read all threads info.
 475    */
 476   char taskpath[PATH_MAX];
 477   DIR *dirp;
 478   struct dirent *entry;
 479 
 480   snprintf(taskpath, PATH_MAX, "/proc/%d/task", ph->pid);
 481   dirp = opendir(taskpath);
 482   int lwp_id;
 483   while ((entry = readdir(dirp)) != NULL) {
 484     if (*entry->d_name == '.') {
 485       continue;
 486     }
 487     lwp_id = atoi(entry->d_name);
 488     if (lwp_id == ph->pid) {
 489       continue;
 490     }
 491     if (!process_doesnt_exist(lwp_id)) {
 492       add_thread_info(ph, lwp_id);
 493     }



 494   }
 495   closedir(dirp);
 496 
 497   // attach to the threads
 498   thr = ph->threads;
 499 
 500   while (thr) {
 501     thread_info* current_thr = thr;
 502     thr = thr->next;
 503     // don't attach to the main thread again
 504     if (ph->pid != current_thr->lwp_id) {
 505       if ((attach_status = ptrace_attach(current_thr->lwp_id, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
 506         if (attach_status == ATTACH_THREAD_DEAD) {
 507           // Remove this thread from the threads list
 508           delete_thread_info(ph, current_thr);
 509         }
 510         else {
 511           Prelease(ph);
 512           return NULL;
 513         } // ATTACH_THREAD_DEAD
 514       } // !ATTACH_SUCCESS
 515     }
< prev index next >