提交 7461dc56 编写于 作者: A alanb

6649594: Intermittent IOExceptions during dynamic attach on linux and solaris

Reviewed-by: dcubed, dholmes
上级 36411c2c
......@@ -32,11 +32,15 @@
#include <sys/un.h>
#include <sys/stat.h>
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path)
#endif
// The attach mechanism on Linux uses a UNIX domain socket. An attach listener
// thread is created at startup or is created on-demand via a signal from
// the client tool. The attach listener creates a socket and binds it to a file
// in the filesystem. The attach listener then acts as a simple (single-
// threaded) server - tt waits for a client to connect, reads the request,
// threaded) server - it waits for a client to connect, reads the request,
// executes it, and returns the response to the client via the socket
// connection.
//
......@@ -54,7 +58,7 @@ class LinuxAttachOperation;
class LinuxAttachListener: AllStatic {
private:
// the path to which we bind the UNIX domain socket
static char _path[PATH_MAX+1];
static char _path[UNIX_PATH_MAX];
static bool _has_path;
// the file descriptor for the listening socket
......@@ -64,8 +68,8 @@ class LinuxAttachListener: AllStatic {
if (path == NULL) {
_has_path = false;
} else {
strncpy(_path, path, PATH_MAX);
_path[PATH_MAX] = '\0';
strncpy(_path, path, UNIX_PATH_MAX);
_path[UNIX_PATH_MAX-1] = '\0';
_has_path = true;
}
}
......@@ -113,7 +117,7 @@ class LinuxAttachOperation: public AttachOperation {
};
// statics
char LinuxAttachListener::_path[PATH_MAX+1];
char LinuxAttachListener::_path[UNIX_PATH_MAX];
bool LinuxAttachListener::_has_path;
int LinuxAttachListener::_listener = -1;
......@@ -163,54 +167,53 @@ extern "C" {
// Initialization - create a listener socket and bind it to a file
int LinuxAttachListener::init() {
char path[PATH_MAX+1]; // socket file
int listener; // listener socket (file descriptor)
char path[UNIX_PATH_MAX]; // socket file
char initial_path[UNIX_PATH_MAX]; // socket file during setup
int listener; // listener socket (file descriptor)
// register function to cleanup
::atexit(listener_cleanup);
int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
if (n <= (int)UNIX_PATH_MAX) {
n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
}
if (n > (int)UNIX_PATH_MAX) {
return -1;
}
// create the listener socket
listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
if (listener == -1) {
return -1;
}
int res = -1;
// bind socket
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
// FIXME: Prior to b39 the tool-side API expected to find the well
// known file in the working directory. To allow this libjvm.so work with
// a pre-b39 SDK we create it in the working directory if
// +StartAttachListener is used is used. All unit tests for this feature
// currently used this flag. Once b39 SDK has been promoted we can remove
// this code.
if (StartAttachListener) {
sprintf(path, ".java_pid%d", os::current_process_id());
strcpy(addr.sun_path, path);
::unlink(path);
res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr));
}
if (res == -1) {
snprintf(path, PATH_MAX+1, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
strcpy(addr.sun_path, path);
::unlink(path);
res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr));
}
strcpy(addr.sun_path, initial_path);
::unlink(initial_path);
int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr));
if (res == -1) {
RESTARTABLE(::close(listener), res);
return -1;
}
set_path(path);
// put in listen mode and set permission
if ((::listen(listener, 5) == -1) || (::chmod(path, S_IREAD|S_IWRITE) == -1)) {
// put in listen mode, set permissions, and rename into place
res = ::listen(listener, 5);
if (res == 0) {
RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
if (res == 0) {
res = ::rename(initial_path, path);
}
}
if (res == -1) {
RESTARTABLE(::close(listener), res);
::unlink(path);
set_path(NULL);
::unlink(initial_path);
return -1;
}
set_path(path);
set_listener(listener);
return 0;
......
......@@ -364,6 +364,7 @@ extern "C" {
// Create the door
int SolarisAttachListener::create_door() {
char door_path[PATH_MAX+1];
char initial_path[PATH_MAX+1];
int fd, res;
// register exit function
......@@ -375,36 +376,46 @@ int SolarisAttachListener::create_door() {
return -1;
}
// create initial file to attach door descriptor
snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
RESTARTABLE(::creat(door_path, S_IRUSR | S_IWUSR), fd);
snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
if (fd == -1) {
debug_only(warning("attempt to create %s failed", door_path));
debug_only(warning("attempt to create %s failed", initial_path));
::door_revoke(dd);
return -1;
}
assert(fd >= 0, "bad file descriptor");
set_door_path(door_path);
RESTARTABLE(::close(fd), res);
// attach the door descriptor to the file
if ((res = ::fattach(dd, door_path)) == -1) {
if ((res = ::fattach(dd, initial_path)) == -1) {
// if busy then detach and try again
if (errno == EBUSY) {
::fdetach(door_path);
res = ::fattach(dd, door_path);
::fdetach(initial_path);
res = ::fattach(dd, initial_path);
}
if (res == -1) {
::door_revoke(dd);
dd = -1;
}
}
// rename file so that clients can attach
if (dd >= 0) {
if (::rename(initial_path, door_path) == -1) {
RESTARTABLE(::close(dd), res);
::fdetach(initial_path);
dd = -1;
}
}
if (dd >= 0) {
set_door_descriptor(dd);
set_door_path(door_path);
} else {
// unable to create door or attach it to the file
::unlink(door_path);
set_door_path(NULL);
// unable to create door, attach it to file, or rename file into place
::unlink(initial_path);
return -1;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册