@@ -76,17 +76,7 @@ class PosixAttachListener: AllStatic {
76
76
77
77
static bool _atexit_registered;
78
78
79
- // reads a request from the given connected socket
80
- static PosixAttachOperation* read_request (int s);
81
-
82
79
public:
83
- enum {
84
- ATTACH_PROTOCOL_VER = 1 // protocol version
85
- };
86
- enum {
87
- ATTACH_ERROR_BADVERSION = 101 // error codes
88
- };
89
-
90
80
static void set_path (char * path) {
91
81
if (path == nullptr ) {
92
82
_path[0 ] = ' \0 ' ;
@@ -107,25 +97,61 @@ class PosixAttachListener: AllStatic {
107
97
static bool has_path () { return _has_path; }
108
98
static int listener () { return _listener; }
109
99
110
- // write the given buffer to a socket
111
- static int write_fully (int s, char * buf, size_t len);
112
-
113
100
static PosixAttachOperation* dequeue ();
114
101
};
115
102
103
+ class SocketChannel : public AttachOperation ::RequestReader, public AttachOperation::ReplyWriter {
104
+ private:
105
+ int _socket;
106
+ public:
107
+ SocketChannel (int socket) : _socket(socket) {}
108
+ ~SocketChannel () {
109
+ close ();
110
+ }
111
+
112
+ bool opened () const {
113
+ return _socket != -1 ;
114
+ }
115
+
116
+ void close () {
117
+ if (opened ()) {
118
+ ::close (_socket);
119
+ _socket = -1 ;
120
+ }
121
+ }
122
+
123
+ // RequestReader
124
+ int read (void * buffer, int size) override {
125
+ ssize_t n;
126
+ RESTARTABLE (::read (_socket, buffer, (size_t )size), n);
127
+ return checked_cast<int >(n);
128
+ }
129
+
130
+ // ReplyWriter
131
+ int write (const void * buffer, int size) override {
132
+ ssize_t n;
133
+ RESTARTABLE (::write (_socket, buffer, size), n);
134
+ return checked_cast<int >(n);
135
+ }
136
+ // called after writing all data
137
+ void flush () override {
138
+ ::shutdown (_socket, SHUT_RDWR);
139
+ }
140
+ };
141
+
116
142
class PosixAttachOperation : public AttachOperation {
117
143
private:
118
144
// the connection to the client
119
- int _socket ;
145
+ SocketChannel _socket_channel ;
120
146
121
147
public:
122
- void complete (jint res, bufferedStream* st);
148
+ void complete (jint res, bufferedStream* st) override ;
123
149
124
- void set_socket (int s) { _socket = s; }
125
- int socket () const { return _socket; }
150
+ PosixAttachOperation (int socket) : AttachOperation(), _socket_channel(socket) {
151
+ }
126
152
127
- PosixAttachOperation ( char * name) : AttachOperation(name ) {
128
- set_socket (- 1 );
153
+ bool read_request ( ) {
154
+ return AttachOperation::read_request (&_socket_channel, &_socket_channel );
129
155
}
130
156
};
131
157
@@ -135,35 +161,6 @@ bool PosixAttachListener::_has_path;
135
161
volatile int PosixAttachListener::_listener = -1 ;
136
162
bool PosixAttachListener::_atexit_registered = false ;
137
163
138
- // Supporting class to help split a buffer into individual components
139
- class ArgumentIterator : public StackObj {
140
- private:
141
- char * _pos;
142
- char * _end;
143
- public:
144
- ArgumentIterator (char * arg_buffer, size_t arg_size) {
145
- _pos = arg_buffer;
146
- _end = _pos + arg_size - 1 ;
147
- }
148
- char * next () {
149
- if (*_pos == ' \0 ' ) {
150
- // advance the iterator if possible (null arguments)
151
- if (_pos < _end) {
152
- _pos += 1 ;
153
- }
154
- return nullptr ;
155
- }
156
- char * res = _pos;
157
- char * next_pos = strchr (_pos, ' \0 ' );
158
- if (next_pos < _end) {
159
- next_pos++;
160
- }
161
- _pos = next_pos;
162
- return res;
163
- }
164
- };
165
-
166
-
167
164
// atexit hook to stop listener and unlink the file that it is
168
165
// bound too.
169
166
extern " C" {
@@ -249,103 +246,6 @@ int PosixAttachListener::init() {
249
246
return 0 ;
250
247
}
251
248
252
- // Given a socket that is connected to a peer we read the request and
253
- // create an AttachOperation. As the socket is blocking there is potential
254
- // for a denial-of-service if the peer does not response. However this happens
255
- // after the peer credentials have been checked and in the worst case it just
256
- // means that the attach listener thread is blocked.
257
- //
258
- PosixAttachOperation* PosixAttachListener::read_request (int s) {
259
- char ver_str[8 ];
260
- os::snprintf_checked (ver_str, sizeof (ver_str), " %d" , ATTACH_PROTOCOL_VER);
261
-
262
- // The request is a sequence of strings so we first figure out the
263
- // expected count and the maximum possible length of the request.
264
- // The request is:
265
- // <ver>0<cmd>0<arg>0<arg>0<arg>0
266
- // where <ver> is the protocol version (1), <cmd> is the command
267
- // name ("load", "datadump", ...), and <arg> is an argument
268
- int expected_str_count = 2 + AttachOperation::arg_count_max;
269
- const size_t max_len = (sizeof (ver_str) + 1 ) + (AttachOperation::name_length_max + 1 ) +
270
- AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1 );
271
-
272
- char buf[max_len];
273
- int str_count = 0 ;
274
-
275
- // Read until all (expected) strings have been read, the buffer is
276
- // full, or EOF.
277
-
278
- size_t off = 0 ;
279
- size_t left = max_len;
280
-
281
- do {
282
- ssize_t n;
283
- RESTARTABLE (read (s, buf+off, left), n);
284
- assert (n <= checked_cast<ssize_t >(left), " buffer was too small, impossible!" );
285
- buf[max_len - 1 ] = ' \0 ' ;
286
- if (n == -1 ) {
287
- return nullptr ; // reset by peer or other error
288
- }
289
- if (n == 0 ) {
290
- break ;
291
- }
292
- for (ssize_t i=0 ; i<n; i++) {
293
- if (buf[off+i] == 0 ) {
294
- // EOS found
295
- str_count++;
296
-
297
- // The first string is <ver> so check it now to
298
- // check for protocol mismatch
299
- if (str_count == 1 ) {
300
- if ((strlen (buf) != strlen (ver_str)) ||
301
- (atoi (buf) != ATTACH_PROTOCOL_VER)) {
302
- char msg[32 ];
303
- os::snprintf_checked (msg, sizeof (msg), " %d\n " , ATTACH_ERROR_BADVERSION);
304
- write_fully (s, msg, strlen (msg));
305
- return nullptr ;
306
- }
307
- }
308
- }
309
- }
310
- off += n;
311
- left -= n;
312
- } while (left > 0 && str_count < expected_str_count);
313
-
314
- if (str_count != expected_str_count) {
315
- return nullptr ; // incomplete request
316
- }
317
-
318
- // parse request
319
-
320
- ArgumentIterator args (buf, (max_len)-left);
321
-
322
- // version already checked
323
- char * v = args.next ();
324
-
325
- char * name = args.next ();
326
- if (name == nullptr || strlen (name) > AttachOperation::name_length_max) {
327
- return nullptr ;
328
- }
329
-
330
- PosixAttachOperation* op = new PosixAttachOperation (name);
331
-
332
- for (int i=0 ; i<AttachOperation::arg_count_max; i++) {
333
- char * arg = args.next ();
334
- if (arg == nullptr ) {
335
- op->set_arg (i, nullptr );
336
- } else {
337
- if (strlen (arg) > AttachOperation::arg_length_max) {
338
- delete op;
339
- return nullptr ;
340
- }
341
- op->set_arg (i, arg);
342
- }
343
- }
344
-
345
- op->set_socket (s);
346
- return op;
347
- }
348
-
349
249
// Dequeue an operation
350
250
//
351
251
// In the Linux and BSD implementations, there is only a single operation and
@@ -400,31 +300,16 @@ PosixAttachOperation* PosixAttachListener::dequeue() {
400
300
#endif
401
301
402
302
// peer credential look okay so we read the request
403
- PosixAttachOperation* op = read_request (s);
404
- if (op == nullptr ) {
405
- ::close (s) ;
303
+ PosixAttachOperation* op = new PosixAttachOperation (s);
304
+ if (!op-> read_request () ) {
305
+ delete op ;
406
306
continue ;
407
307
} else {
408
308
return op;
409
309
}
410
310
}
411
311
}
412
312
413
- // write the given buffer to the socket
414
- int PosixAttachListener::write_fully (int s, char * buf, size_t len) {
415
- do {
416
- ssize_t n = ::write (s, buf, len);
417
- if (n == -1 ) {
418
- if (errno != EINTR) return -1 ;
419
- } else {
420
- buf += n;
421
- len -= n;
422
- }
423
- }
424
- while (len > 0 );
425
- return 0 ;
426
- }
427
-
428
313
// Complete an operation by sending the operation result and any result
429
314
// output to the client. At this time the socket is in blocking mode so
430
315
// potentially we can block if there is a lot of data and the client is
@@ -437,19 +322,7 @@ void PosixAttachOperation::complete(jint result, bufferedStream* st) {
437
322
JavaThread* thread = JavaThread::current ();
438
323
ThreadBlockInVM tbivm (thread);
439
324
440
- // write operation result
441
- char msg[32 ];
442
- os::snprintf_checked (msg, sizeof (msg), " %d\n " , result);
443
- int rc = PosixAttachListener::write_fully (this ->socket (), msg, strlen (msg));
444
-
445
- // write any result data
446
- if (rc == 0 ) {
447
- PosixAttachListener::write_fully (this ->socket (), (char *) st->base (), st->size ());
448
- ::shutdown (this ->socket (), 2);
449
- }
450
-
451
- // done
452
- ::close (this ->socket ());
325
+ write_reply (&_socket_channel, result, st);
453
326
454
327
delete this ;
455
328
}
@@ -490,6 +363,8 @@ void AttachListener::vm_start() {
490
363
}
491
364
492
365
int AttachListener::pd_init () {
366
+ AttachListener::set_supported_version (ATTACH_API_V2);
367
+
493
368
JavaThread* thread = JavaThread::current ();
494
369
ThreadBlockInVM tbivm (thread);
495
370
0 commit comments