< prev index next >

src/os/bsd/vm/attachListener_bsd.cpp

Print this page
rev 9381 : 8225690: Multiple AttachListener threads can be created
Reviewed-by: sspitsyn, cjplummer
   1 /*
   2  * Copyright (c) 2005, 2013, 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  *


  50 // As the socket is a UNIX domain socket it means that only clients on the
  51 // local machine can connect. In addition there are two other aspects to
  52 // the security:
  53 // 1. The well known file that the socket is bound to has permission 400
  54 // 2. When a client connect, the SO_PEERCRED socket option is used to
  55 //    obtain the credentials of client. We check that the effective uid
  56 //    of the client matches this process.
  57 
  58 // forward reference
  59 class BsdAttachOperation;
  60 
  61 class BsdAttachListener: AllStatic {
  62  private:
  63   // the path to which we bind the UNIX domain socket
  64   static char _path[UNIX_PATH_MAX];
  65   static bool _has_path;
  66 
  67   // the file descriptor for the listening socket
  68   static int _listener;
  69 
  70   static void set_path(char* path) {
  71     if (path == NULL) {
  72       _has_path = false;
  73     } else {
  74       strncpy(_path, path, UNIX_PATH_MAX);
  75       _path[UNIX_PATH_MAX-1] = '\0';
  76       _has_path = true;
  77     }
  78   }
  79 
  80   static void set_listener(int s)               { _listener = s; }
  81 
  82   // reads a request from the given connected socket
  83   static BsdAttachOperation* read_request(int s);
  84 
  85  public:
  86   enum {
  87     ATTACH_PROTOCOL_VER = 1                     // protocol version
  88   };
  89   enum {
  90     ATTACH_ERROR_BADVERSION     = 101           // error codes
  91   };
  92 













  93   // initialize the listener, returns 0 if okay
  94   static int init();
  95 
  96   static char* path()                   { return _path; }
  97   static bool has_path()                { return _has_path; }
  98   static int listener()                 { return _listener; }
  99 
 100   // write the given buffer to a socket
 101   static int write_fully(int s, char* buf, int len);
 102 
 103   static BsdAttachOperation* dequeue();
 104 };
 105 
 106 class BsdAttachOperation: public AttachOperation {
 107  private:
 108   // the connection to the client
 109   int _socket;
 110 
 111  public:
 112   void complete(jint res, bufferedStream* st);
 113 
 114   void set_socket(int s)                                { _socket = s; }
 115   int socket() const                                    { return _socket; }
 116 
 117   BsdAttachOperation(char* name) : AttachOperation(name) {
 118     set_socket(-1);
 119   }
 120 };
 121 
 122 // statics
 123 char BsdAttachListener::_path[UNIX_PATH_MAX];
 124 bool BsdAttachListener::_has_path;
 125 int BsdAttachListener::_listener = -1;

 126 
 127 // Supporting class to help split a buffer into individual components
 128 class ArgumentIterator : public StackObj {
 129  private:
 130   char* _pos;
 131   char* _end;
 132  public:
 133   ArgumentIterator(char* arg_buffer, size_t arg_size) {
 134     _pos = arg_buffer;
 135     _end = _pos + arg_size - 1;
 136   }
 137   char* next() {
 138     if (*_pos == '\0') {
 139       return NULL;
 140     }
 141     char* res = _pos;
 142     char* next_pos = strchr(_pos, '\0');
 143     if (next_pos < _end)  {
 144       next_pos++;
 145     }
 146     _pos = next_pos;
 147     return res;
 148   }
 149 };
 150 
 151 
 152 // atexit hook to stop listener and unlink the file that it is
 153 // bound too.
 154 extern "C" {
 155   static void listener_cleanup() {
 156     static int cleanup_done;
 157     if (!cleanup_done) {
 158       cleanup_done = 1;
 159       int s = BsdAttachListener::listener();
 160       if (s != -1) {


 161         ::close(s);
 162       }
 163       if (BsdAttachListener::has_path()) {
 164         ::unlink(BsdAttachListener::path());
 165       }
 166     }
 167   }
 168 }
 169 
 170 // Initialization - create a listener socket and bind it to a file
 171 
 172 int BsdAttachListener::init() {
 173   char path[UNIX_PATH_MAX];          // socket file
 174   char initial_path[UNIX_PATH_MAX];  // socket file during setup
 175   int listener;                      // listener socket (file descriptor)
 176 
 177   // register function to cleanup


 178   ::atexit(listener_cleanup);

 179 
 180   int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
 181                    os::get_temp_directory(), os::current_process_id());
 182   if (n < (int)UNIX_PATH_MAX) {
 183     n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
 184   }
 185   if (n >= (int)UNIX_PATH_MAX) {
 186     return -1;
 187   }
 188 
 189   // create the listener socket
 190   listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
 191   if (listener == -1) {
 192     return -1;
 193   }
 194 
 195   // bind socket
 196   struct sockaddr_un addr;
 197   addr.sun_family = AF_UNIX;
 198   strcpy(addr.sun_path, initial_path);


 458     if (ret == -1) {
 459       debug_only(warning("failed to remove stale attach pid file at %s", fn));
 460     }
 461   }
 462 }
 463 
 464 int AttachListener::pd_init() {
 465   JavaThread* thread = JavaThread::current();
 466   ThreadBlockInVM tbivm(thread);
 467 
 468   thread->set_suspend_equivalent();
 469   // cleared by handle_special_suspend_equivalent_condition() or
 470   // java_suspend_self() via check_and_wait_while_suspended()
 471 
 472   int ret_code = BsdAttachListener::init();
 473 
 474   // were we externally suspended while we were waiting?
 475   thread->check_and_wait_while_suspended();
 476 
 477   return ret_code;






















 478 }
 479 
 480 // Attach Listener is started lazily except in the case when
 481 // +ReduseSignalUsage is used
 482 bool AttachListener::init_at_startup() {
 483   if (ReduceSignalUsage) {
 484     return true;
 485   } else {
 486     return false;
 487   }
 488 }
 489 
 490 // If the file .attach_pid<pid> exists in the working directory
 491 // or /tmp then this is the trigger to start the attach mechanism
 492 bool AttachListener::is_init_trigger() {
 493   if (init_at_startup() || is_initialized()) {
 494     return false;               // initialized at startup or already initialized
 495   }
 496   char path[PATH_MAX + 1];
 497   int ret;


   1 /*
   2  * Copyright (c) 2005, 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  *


  50 // As the socket is a UNIX domain socket it means that only clients on the
  51 // local machine can connect. In addition there are two other aspects to
  52 // the security:
  53 // 1. The well known file that the socket is bound to has permission 400
  54 // 2. When a client connect, the SO_PEERCRED socket option is used to
  55 //    obtain the credentials of client. We check that the effective uid
  56 //    of the client matches this process.
  57 
  58 // forward reference
  59 class BsdAttachOperation;
  60 
  61 class BsdAttachListener: AllStatic {
  62  private:
  63   // the path to which we bind the UNIX domain socket
  64   static char _path[UNIX_PATH_MAX];
  65   static bool _has_path;
  66 
  67   // the file descriptor for the listening socket
  68   static int _listener;
  69 
  70   static bool _atexit_registered;










  71 
  72   // reads a request from the given connected socket
  73   static BsdAttachOperation* read_request(int s);
  74 
  75  public:
  76   enum {
  77     ATTACH_PROTOCOL_VER = 1                     // protocol version
  78   };
  79   enum {
  80     ATTACH_ERROR_BADVERSION     = 101           // error codes
  81   };
  82 
  83   static void set_path(char* path) {
  84     if (path == NULL) {
  85       _path[0] = '\0';
  86       _has_path = false;
  87     } else {
  88       strncpy(_path, path, UNIX_PATH_MAX);
  89       _path[UNIX_PATH_MAX-1] = '\0';
  90       _has_path = true;
  91     }
  92   }
  93 
  94   static void set_listener(int s)               { _listener = s; }
  95 
  96   // initialize the listener, returns 0 if okay
  97   static int init();
  98 
  99   static char* path()                   { return _path; }
 100   static bool has_path()                { return _has_path; }
 101   static int listener()                 { return _listener; }
 102 
 103   // write the given buffer to a socket
 104   static int write_fully(int s, char* buf, int len);
 105 
 106   static BsdAttachOperation* dequeue();
 107 };
 108 
 109 class BsdAttachOperation: public AttachOperation {
 110  private:
 111   // the connection to the client
 112   int _socket;
 113 
 114  public:
 115   void complete(jint res, bufferedStream* st);
 116 
 117   void set_socket(int s)                                { _socket = s; }
 118   int socket() const                                    { return _socket; }
 119 
 120   BsdAttachOperation(char* name) : AttachOperation(name) {
 121     set_socket(-1);
 122   }
 123 };
 124 
 125 // statics
 126 char BsdAttachListener::_path[UNIX_PATH_MAX];
 127 bool BsdAttachListener::_has_path;
 128 int BsdAttachListener::_listener = -1;
 129 bool BsdAttachListener::_atexit_registered = false;
 130 
 131 // Supporting class to help split a buffer into individual components
 132 class ArgumentIterator : public StackObj {
 133  private:
 134   char* _pos;
 135   char* _end;
 136  public:
 137   ArgumentIterator(char* arg_buffer, size_t arg_size) {
 138     _pos = arg_buffer;
 139     _end = _pos + arg_size - 1;
 140   }
 141   char* next() {
 142     if (*_pos == '\0') {
 143       return NULL;
 144     }
 145     char* res = _pos;
 146     char* next_pos = strchr(_pos, '\0');
 147     if (next_pos < _end)  {
 148       next_pos++;
 149     }
 150     _pos = next_pos;
 151     return res;
 152   }
 153 };
 154 
 155 
 156 // atexit hook to stop listener and unlink the file that it is
 157 // bound too.
 158 extern "C" {
 159   static void listener_cleanup() {



 160     int s = BsdAttachListener::listener();
 161     if (s != -1) {
 162       BsdAttachListener::set_listener(-1);
 163       ::shutdown(s, SHUT_RDWR);
 164       ::close(s);
 165     }
 166     if (BsdAttachListener::has_path()) {
 167       ::unlink(BsdAttachListener::path());
 168       BsdAttachListener::set_path(NULL);
 169     }
 170   }
 171 }
 172 
 173 // Initialization - create a listener socket and bind it to a file
 174 
 175 int BsdAttachListener::init() {
 176   char path[UNIX_PATH_MAX];          // socket file
 177   char initial_path[UNIX_PATH_MAX];  // socket file during setup
 178   int listener;                      // listener socket (file descriptor)
 179 
 180   // register function to cleanup
 181   if (!_atexit_registered) {
 182     _atexit_registered = true;
 183     ::atexit(listener_cleanup);
 184   }
 185 
 186   int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
 187                    os::get_temp_directory(), os::current_process_id());
 188   if (n < (int)UNIX_PATH_MAX) {
 189     n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
 190   }
 191   if (n >= (int)UNIX_PATH_MAX) {
 192     return -1;
 193   }
 194 
 195   // create the listener socket
 196   listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
 197   if (listener == -1) {
 198     return -1;
 199   }
 200 
 201   // bind socket
 202   struct sockaddr_un addr;
 203   addr.sun_family = AF_UNIX;
 204   strcpy(addr.sun_path, initial_path);


 464     if (ret == -1) {
 465       debug_only(warning("failed to remove stale attach pid file at %s", fn));
 466     }
 467   }
 468 }
 469 
 470 int AttachListener::pd_init() {
 471   JavaThread* thread = JavaThread::current();
 472   ThreadBlockInVM tbivm(thread);
 473 
 474   thread->set_suspend_equivalent();
 475   // cleared by handle_special_suspend_equivalent_condition() or
 476   // java_suspend_self() via check_and_wait_while_suspended()
 477 
 478   int ret_code = BsdAttachListener::init();
 479 
 480   // were we externally suspended while we were waiting?
 481   thread->check_and_wait_while_suspended();
 482 
 483   return ret_code;
 484 }
 485 
 486 bool AttachListener::check_socket_file() {
 487   int ret;
 488   struct stat st;
 489   ret = stat(BsdAttachListener::path(), &st);
 490   if (ret == -1) { // need to restart attach listener.
 491     debug_only(warning("Socket file %s does not exist - Restart Attach Listener",
 492                       BsdAttachListener::path()));
 493 
 494     listener_cleanup();
 495 
 496     // wait to terminate current attach listener instance...
 497 
 498     while (AttachListener::transit_state(AL_INITIALIZING,
 499 
 500                                          AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
 501       os::yield();
 502     }
 503     return is_init_trigger();
 504   }
 505   return false;
 506 }
 507 
 508 // Attach Listener is started lazily except in the case when
 509 // +ReduseSignalUsage is used
 510 bool AttachListener::init_at_startup() {
 511   if (ReduceSignalUsage) {
 512     return true;
 513   } else {
 514     return false;
 515   }
 516 }
 517 
 518 // If the file .attach_pid<pid> exists in the working directory
 519 // or /tmp then this is the trigger to start the attach mechanism
 520 bool AttachListener::is_init_trigger() {
 521   if (init_at_startup() || is_initialized()) {
 522     return false;               // initialized at startup or already initialized
 523   }
 524   char path[PATH_MAX + 1];
 525   int ret;


< prev index next >