1 /*
2 * Copyright (c) 2005, 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 *
58 // the result is returned via a UNIX domain socket. A pair of connected
59 // sockets (socketpair) is created in the enqueue function and the file
60 // descriptor for one of the sockets is returned to the client as the
61 // return from the door call. The other end is retained in this process.
62 // When the operation completes the result is sent to the client and
63 // the socket is closed.
64
65 // forward reference
66 class SolarisAttachOperation;
67
68 class SolarisAttachListener: AllStatic {
69 private:
70
71 // the path to which we attach the door file descriptor
72 static char _door_path[PATH_MAX+1];
73 static volatile bool _has_door_path;
74
75 // door descriptor returned by door_create
76 static int _door_descriptor;
77
78 static void set_door_path(char* path) {
79 if (path == NULL) {
80 _has_door_path = false;
81 } else {
82 strncpy(_door_path, path, PATH_MAX);
83 _door_path[PATH_MAX] = '\0'; // ensure it's nul terminated
84 _has_door_path = true;
85 }
86 }
87
88 static void set_door_descriptor(int dd) { _door_descriptor = dd; }
89
90 // mutex to protect operation list
91 static mutex_t _mutex;
92
93 // semaphore to wakeup listener thread
94 static sema_t _wakeup;
95
96 static mutex_t* mutex() { return &_mutex; }
97 static sema_t* wakeup() { return &_wakeup; }
98
99 // enqueued operation list
100 static SolarisAttachOperation* _head;
101 static SolarisAttachOperation* _tail;
102
103 static SolarisAttachOperation* head() { return _head; }
104 static void set_head(SolarisAttachOperation* head) { _head = head; }
105
106 static SolarisAttachOperation* tail() { return _tail; }
107 static void set_tail(SolarisAttachOperation* tail) { _tail = tail; }
108
109 // create the door
110 static int create_door();
111
112 public:
113 enum {
114 ATTACH_PROTOCOL_VER = 1 // protocol version
115 };
116 enum {
117 ATTACH_ERROR_BADREQUEST = 100, // error code returned by
118 ATTACH_ERROR_BADVERSION = 101, // the door call
119 ATTACH_ERROR_RESOURCE = 102,
120 ATTACH_ERROR_INTERNAL = 103,
121 ATTACH_ERROR_DENIED = 104
122 };
123
124 // initialize the listener
125 static int init();
126
127 static bool has_door_path() { return _has_door_path; }
128 static char* door_path() { return _door_path; }
129 static int door_descriptor() { return _door_descriptor; }
130
131 // enqueue an operation
132 static void enqueue(SolarisAttachOperation* op);
133
134 // dequeue an operation
135 static SolarisAttachOperation* dequeue();
136 };
137
138
139 // SolarisAttachOperation is an AttachOperation that additionally encapsulates
140 // a socket connection to the requesting client/tool. SolarisAttachOperation
141 // can additionally be held in a linked list.
142
143 class SolarisAttachOperation: public AttachOperation {
152
153 SolarisAttachOperation* next() { return _next; }
154 void set_next(SolarisAttachOperation* next) { _next = next; }
155
156 public:
157 void complete(jint res, bufferedStream* st);
158
159 int socket() const { return _socket; }
160 void set_socket(int s) { _socket = s; }
161
162 SolarisAttachOperation(char* name) : AttachOperation(name) {
163 set_socket(-1);
164 set_next(NULL);
165 }
166 };
167
168 // statics
169 char SolarisAttachListener::_door_path[PATH_MAX+1];
170 volatile bool SolarisAttachListener::_has_door_path;
171 int SolarisAttachListener::_door_descriptor = -1;
172 mutex_t SolarisAttachListener::_mutex;
173 sema_t SolarisAttachListener::_wakeup;
174 SolarisAttachOperation* SolarisAttachListener::_head = NULL;
175 SolarisAttachOperation* SolarisAttachListener::_tail = NULL;
176
177 // Supporting class to help split a buffer into individual components
178 class ArgumentIterator : public StackObj {
179 private:
180 char* _pos;
181 char* _end;
182 public:
183 ArgumentIterator(char* arg_buffer, size_t arg_size) {
184 _pos = arg_buffer;
185 _end = _pos + arg_size - 1;
186 }
187 char* next() {
188 if (*_pos == '\0') {
189 // advance the iterator if possible (null arguments)
190 if (_pos < _end) {
191 _pos += 1;
347 }
348 }
349
350 // Return 0 (success) + file descriptor, or non-0 (error)
351 if (res == 0) {
352 door_desc_t desc;
353 // DOOR_RELEASE flag makes sure fd is closed after passing it to
354 // the client. See door_return(3DOOR) man page.
355 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
356 desc.d_data.d_desc.d_descriptor = return_fd;
357 door_return((char*)&res, sizeof(res), &desc, 1);
358 } else {
359 door_return((char*)&res, sizeof(res), NULL, 0);
360 }
361 }
362 }
363
364 // atexit hook to detach the door and remove the file
365 extern "C" {
366 static void listener_cleanup() {
367 static int cleanup_done;
368 if (!cleanup_done) {
369 cleanup_done = 1;
370 int dd = SolarisAttachListener::door_descriptor();
371 if (dd >= 0) {
372 ::close(dd);
373 }
374 if (SolarisAttachListener::has_door_path()) {
375 char* path = SolarisAttachListener::door_path();
376 ::fdetach(path);
377 ::unlink(path);
378 }
379 }
380 }
381 }
382
383 // Create the door
384 int SolarisAttachListener::create_door() {
385 char door_path[PATH_MAX+1];
386 char initial_path[PATH_MAX+1];
387 int fd, res;
388
389 // register exit function
390 ::atexit(listener_cleanup);
391
392 // create the door descriptor
393 int dd = ::door_create(enqueue_proc, NULL, 0);
394 if (dd < 0) {
395 return -1;
396 }
397
398 // create initial file to attach door descriptor
399 snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
400 os::get_temp_directory(), os::current_process_id());
401 snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
402 RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
403 if (fd == -1) {
404 log_debug(attach)("attempt to create door file %s failed (%d)", initial_path, errno);
405 ::door_revoke(dd);
406 return -1;
407 }
408 assert(fd >= 0, "bad file descriptor");
409 ::close(fd);
410
624 thread->set_suspend_equivalent();
625 // cleared by handle_special_suspend_equivalent_condition() or
626 // java_suspend_self()
627
628 int ret_code = SolarisAttachListener::init();
629
630 // were we externally suspended while we were waiting?
631 thread->check_and_wait_while_suspended();
632
633 return ret_code;
634 }
635
636 // Attach Listener is started lazily except in the case when
637 // +ReduseSignalUsage is used
638 bool AttachListener::init_at_startup() {
639 if (ReduceSignalUsage) {
640 return true;
641 } else {
642 return false;
643 }
644 }
645
646 // If the file .attach_pid<pid> exists in the working directory
647 // or /tmp then this is the trigger to start the attach mechanism
648 bool AttachListener::is_init_trigger() {
649 if (init_at_startup() || is_initialized()) {
650 return false; // initialized at startup or already initialized
651 }
652 char fn[PATH_MAX + 1];
653 int ret;
654 struct stat64 st;
655 sprintf(fn, ".attach_pid%d", os::current_process_id());
656 RESTARTABLE(::stat64(fn, &st), ret);
657 if (ret == -1) {
658 log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
659 snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
660 os::get_temp_directory(), os::current_process_id());
661 RESTARTABLE(::stat64(fn, &st), ret);
662 if (ret == -1) {
663 log_debug(attach)("Failed to find attach file: %s", fn);
|
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 *
58 // the result is returned via a UNIX domain socket. A pair of connected
59 // sockets (socketpair) is created in the enqueue function and the file
60 // descriptor for one of the sockets is returned to the client as the
61 // return from the door call. The other end is retained in this process.
62 // When the operation completes the result is sent to the client and
63 // the socket is closed.
64
65 // forward reference
66 class SolarisAttachOperation;
67
68 class SolarisAttachListener: AllStatic {
69 private:
70
71 // the path to which we attach the door file descriptor
72 static char _door_path[PATH_MAX+1];
73 static volatile bool _has_door_path;
74
75 // door descriptor returned by door_create
76 static int _door_descriptor;
77
78 static bool _atexit_registered;
79
80 // mutex to protect operation list
81 static mutex_t _mutex;
82
83 // semaphore to wakeup listener thread
84 static sema_t _wakeup;
85
86 static mutex_t* mutex() { return &_mutex; }
87 static sema_t* wakeup() { return &_wakeup; }
88
89 // enqueued operation list
90 static SolarisAttachOperation* _head;
91 static SolarisAttachOperation* _tail;
92
93 static SolarisAttachOperation* head() { return _head; }
94 static void set_head(SolarisAttachOperation* head) { _head = head; }
95
96 static SolarisAttachOperation* tail() { return _tail; }
97 static void set_tail(SolarisAttachOperation* tail) { _tail = tail; }
98
99 // create the door
100 static int create_door();
101
102 public:
103 enum {
104 ATTACH_PROTOCOL_VER = 1 // protocol version
105 };
106 enum {
107 ATTACH_ERROR_BADREQUEST = 100, // error code returned by
108 ATTACH_ERROR_BADVERSION = 101, // the door call
109 ATTACH_ERROR_RESOURCE = 102,
110 ATTACH_ERROR_INTERNAL = 103,
111 ATTACH_ERROR_DENIED = 104
112 };
113
114 static void set_door_path(char* path) {
115 if (path == NULL) {
116 _door_path[0] = '\0';
117 _has_door_path = false;
118 } else {
119 strncpy(_door_path, path, PATH_MAX);
120 _door_path[PATH_MAX] = '\0'; // ensure it's nul terminated
121 _has_door_path = true;
122 }
123 }
124
125 static void set_door_descriptor(int dd) { _door_descriptor = dd; }
126
127 // initialize the listener
128 static int init();
129
130 static bool has_door_path() { return _has_door_path; }
131 static char* door_path() { return _door_path; }
132 static int door_descriptor() { return _door_descriptor; }
133
134 // enqueue an operation
135 static void enqueue(SolarisAttachOperation* op);
136
137 // dequeue an operation
138 static SolarisAttachOperation* dequeue();
139 };
140
141
142 // SolarisAttachOperation is an AttachOperation that additionally encapsulates
143 // a socket connection to the requesting client/tool. SolarisAttachOperation
144 // can additionally be held in a linked list.
145
146 class SolarisAttachOperation: public AttachOperation {
155
156 SolarisAttachOperation* next() { return _next; }
157 void set_next(SolarisAttachOperation* next) { _next = next; }
158
159 public:
160 void complete(jint res, bufferedStream* st);
161
162 int socket() const { return _socket; }
163 void set_socket(int s) { _socket = s; }
164
165 SolarisAttachOperation(char* name) : AttachOperation(name) {
166 set_socket(-1);
167 set_next(NULL);
168 }
169 };
170
171 // statics
172 char SolarisAttachListener::_door_path[PATH_MAX+1];
173 volatile bool SolarisAttachListener::_has_door_path;
174 int SolarisAttachListener::_door_descriptor = -1;
175 bool SolarisAttachListener::_atexit_registered = false;
176 mutex_t SolarisAttachListener::_mutex;
177 sema_t SolarisAttachListener::_wakeup;
178 SolarisAttachOperation* SolarisAttachListener::_head = NULL;
179 SolarisAttachOperation* SolarisAttachListener::_tail = NULL;
180
181 // Supporting class to help split a buffer into individual components
182 class ArgumentIterator : public StackObj {
183 private:
184 char* _pos;
185 char* _end;
186 public:
187 ArgumentIterator(char* arg_buffer, size_t arg_size) {
188 _pos = arg_buffer;
189 _end = _pos + arg_size - 1;
190 }
191 char* next() {
192 if (*_pos == '\0') {
193 // advance the iterator if possible (null arguments)
194 if (_pos < _end) {
195 _pos += 1;
351 }
352 }
353
354 // Return 0 (success) + file descriptor, or non-0 (error)
355 if (res == 0) {
356 door_desc_t desc;
357 // DOOR_RELEASE flag makes sure fd is closed after passing it to
358 // the client. See door_return(3DOOR) man page.
359 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
360 desc.d_data.d_desc.d_descriptor = return_fd;
361 door_return((char*)&res, sizeof(res), &desc, 1);
362 } else {
363 door_return((char*)&res, sizeof(res), NULL, 0);
364 }
365 }
366 }
367
368 // atexit hook to detach the door and remove the file
369 extern "C" {
370 static void listener_cleanup() {
371 int dd = SolarisAttachListener::door_descriptor();
372 if (dd >= 0) {
373 SolarisAttachListener::set_door_descriptor(-1);
374 ::close(dd);
375 }
376 if (SolarisAttachListener::has_door_path()) {
377 char* path = SolarisAttachListener::door_path();
378 ::fdetach(path);
379 ::unlink(path);
380 SolarisAttachListener::set_door_path(NULL);
381 }
382 }
383 }
384
385 // Create the door
386 int SolarisAttachListener::create_door() {
387 char door_path[PATH_MAX+1];
388 char initial_path[PATH_MAX+1];
389 int fd, res;
390
391 // register exit function
392 if (!_atexit_registered) {
393 _atexit_registered = true;
394 ::atexit(listener_cleanup);
395 }
396
397 // create the door descriptor
398 int dd = ::door_create(enqueue_proc, NULL, 0);
399 if (dd < 0) {
400 return -1;
401 }
402
403 // create initial file to attach door descriptor
404 snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
405 os::get_temp_directory(), os::current_process_id());
406 snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
407 RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
408 if (fd == -1) {
409 log_debug(attach)("attempt to create door file %s failed (%d)", initial_path, errno);
410 ::door_revoke(dd);
411 return -1;
412 }
413 assert(fd >= 0, "bad file descriptor");
414 ::close(fd);
415
629 thread->set_suspend_equivalent();
630 // cleared by handle_special_suspend_equivalent_condition() or
631 // java_suspend_self()
632
633 int ret_code = SolarisAttachListener::init();
634
635 // were we externally suspended while we were waiting?
636 thread->check_and_wait_while_suspended();
637
638 return ret_code;
639 }
640
641 // Attach Listener is started lazily except in the case when
642 // +ReduseSignalUsage is used
643 bool AttachListener::init_at_startup() {
644 if (ReduceSignalUsage) {
645 return true;
646 } else {
647 return false;
648 }
649 }
650
651 bool AttachListener::check_socket_file() {
652 int ret;
653 struct stat64 st;
654 ret = stat64(SolarisAttachListener::door_path(), &st);
655 if (ret == -1) { // need to restart attach listener.
656 log_debug(attach)("Door file %s does not exist - Restart Attach Listener",
657 SolarisAttachListener::door_path());
658
659 listener_cleanup();
660
661 // wait to terminate current attach listener instance...
662 while (AttachListener::transit_state(AL_INITIALIZING,
663 AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
664 os::naked_yield();
665 }
666 return is_init_trigger();
667 }
668 return false;
669 }
670
671 // If the file .attach_pid<pid> exists in the working directory
672 // or /tmp then this is the trigger to start the attach mechanism
673 bool AttachListener::is_init_trigger() {
674 if (init_at_startup() || is_initialized()) {
675 return false; // initialized at startup or already initialized
676 }
677 char fn[PATH_MAX + 1];
678 int ret;
679 struct stat64 st;
680 sprintf(fn, ".attach_pid%d", os::current_process_id());
681 RESTARTABLE(::stat64(fn, &st), ret);
682 if (ret == -1) {
683 log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
684 snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
685 os::get_temp_directory(), os::current_process_id());
686 RESTARTABLE(::stat64(fn, &st), ret);
687 if (ret == -1) {
688 log_debug(attach)("Failed to find attach file: %s", fn);
|