1 /*
2 * Copyright (c) 1999, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdlib.h>
29
30 #include "sysShmem.h"
31 #include "shmemBase.h"
32 #include "jdwpTransport.h" /* for Packet, TransportCallback */
33
34 #if defined(_WIN32)
35 #define PRId64 "I64d"
36 #endif
37
38 #define MIN(x,y) ((x)<(y)?(x):(y))
39
40 /*
41 * This is the base shared memory transport implementation that is used
42 * by both front-end transports (through com.sun.tools.jdi) and
43 * back-end transports (through JDWP_OnLoad and the function tables
44 * it requires). It supports multiple connections for the benefit of the
45 * front-end client; the back end interface assumes only a single connection.
46 */
47
48 #define MAX_IPC_PREFIX 50 /* user-specified or generated name for */
49 /* shared memory seg and prefix for other IPC */
50 #define MAX_IPC_SUFFIX 25 /* suffix to shmem name for other IPC names */
51 #define MAX_IPC_NAME (MAX_IPC_PREFIX + MAX_IPC_SUFFIX)
52
53 #define MAX_GENERATION_RETRIES 20
54 #define SHARED_BUFFER_SIZE 5000
55
56 #define CHECK_ERROR(expr) do { \
57 jint error = (expr); \
58 if (error != SYS_OK) { \
59 setLastError(error); \
60 return error; \
61 } \
62 } while (0)
63
64 /*
65 * The following assertions should hold anytime the stream's mutex is not held
66 */
67 #define STREAM_INVARIANT(stream) \
68 do { \
69 SHMEM_ASSERT((stream->shared->readOffset < SHARED_BUFFER_SIZE) \
70 && (stream->shared->readOffset >= 0)); \
71 SHMEM_ASSERT((stream->shared->writeOffset < SHARED_BUFFER_SIZE) \
72 && (stream->shared->writeOffset >= 0)); \
73 } while (0)
74
75 /*
76 * Transports are duplex, so carve the shared memory into "streams",
77 * one used to send from client to server, the other vice versa.
78 */
79 typedef struct SharedMemoryListener {
80 char mutexName[MAX_IPC_NAME];
81 char acceptEventName[MAX_IPC_NAME];
82 char attachEventName[MAX_IPC_NAME];
83 jboolean isListening;
84 jboolean isAccepted;
85 jlong acceptingPID;
86 jlong attachingPID;
87 } SharedListener;
88
89 typedef struct SharedMemoryTransport {
90 char name[MAX_IPC_PREFIX];
91 sys_ipmutex_t mutex;
92 sys_event_t acceptEvent;
93 sys_event_t attachEvent;
94 sys_shmem_t sharedMemory;
95 SharedListener *shared;
96 } SharedMemoryTransport;
97
98 /*
99 * Access must be syncronized. Holds one shared
100 * memory buffer and its state.
101 */
102 typedef struct SharedStream {
103 char mutexName[MAX_IPC_NAME];
104 char hasDataEventName[MAX_IPC_NAME];
105 char hasSpaceEventName[MAX_IPC_NAME];
106 int readOffset;
107 int writeOffset;
108 jboolean isFull;
109 jbyte buffer[SHARED_BUFFER_SIZE];
110 } SharedStream;
111
112 /*
113 * The two shared streams: client to server and
114 * server to client.
115 */
116 typedef struct SharedMemory {
117 SharedStream toClient;
118 SharedStream toServer;
119 } SharedMemory;
120
121 /*
122 * Local (to process) access to the shared memory
123 * stream. access to hasData and hasSpace synchronized
124 * by OS.
125 */
126 typedef struct Stream {
127 sys_ipmutex_t mutex;
128 sys_event_t hasData;
129 sys_event_t hasSpace;
130 SharedStream *shared;
131 jint state;
132 } Stream;
133
134 /*
135 * Values for Stream.state field above.
136 */
137 #define STATE_CLOSED 0xDEAD
138 #define STATE_OPEN (STATE_CLOSED -1)
139 /*
140 * State checking macro. We compare against the STATE_OPEN value so
141 * that STATE_CLOSED and any other value will be considered closed.
142 * This catches a freed Stream as long as the memory page is still
143 * valid. If the memory page is gone, then there is little that we
144 * can do.
145 */
146 #define IS_STATE_CLOSED(state) (state != STATE_OPEN)
147
148
149 typedef struct SharedMemoryConnection {
150 char name[MAX_IPC_NAME];
151 SharedMemory *shared;
152 sys_shmem_t sharedMemory;
153 Stream incoming;
154 Stream outgoing;
155 sys_process_t otherProcess;
156 sys_event_t shutdown; /* signalled to indicate shutdown */
157 } SharedMemoryConnection;
158
159 static jdwpTransportCallback *callback;
160 static JavaVM *jvm;
161 static int tlsIndex;
162
163 typedef jint (*CreateFunc)(char *name, void *arg);
164
165 /*
166 * Set the per-thread error message (if not already set)
167 */
168 static void
setLastErrorMsg(char * newmsg)169 setLastErrorMsg(char *newmsg) {
170 char *msg;
171
172 msg = (char *)sysTlsGet(tlsIndex);
173 if (msg == NULL) {
174 msg = (*callback->alloc)((int)strlen(newmsg)+1);
175 if (msg != NULL) {
176 strcpy(msg, newmsg);
177 }
178 sysTlsPut(tlsIndex, (void *)msg);
179 }
180 }
181
182 /*
183 * Clear last per-thread error message
184 */
185 static void
clearLastError()186 clearLastError() {
187 char* msg = (char *)sysTlsGet(tlsIndex);
188 if (msg != NULL) {
189 (*callback->free)(msg);
190 sysTlsPut(tlsIndex, NULL);
191 }
192 }
193
194 /*
195 * Set the per-thread error message to the textual representation
196 * of the last system error (if not already set)
197 */
198 static void
setLastError(jint error)199 setLastError(jint error) {
200 char buf[128];
201
202 switch (error) {
203 case SYS_OK : return; /* no-op */
204 case SYS_DIED : strcpy(buf, "Other process terminated"); break;
205 case SYS_TIMEOUT : strcpy(buf, "Timed out"); break;
206 default : sysGetLastError(buf, sizeof(buf));
207 }
208 setLastErrorMsg(buf);
209 }
210
211 jint
shmemBase_initialize(JavaVM * vm,jdwpTransportCallback * cbPtr)212 shmemBase_initialize(JavaVM *vm, jdwpTransportCallback *cbPtr)
213 {
214 jvm = vm;
215 callback = cbPtr;
216 tlsIndex = sysTlsAlloc();
217 return SYS_OK;
218 }
219
220 static jint
createWithGeneratedName(char * prefix,char * nameBuffer,CreateFunc func,void * arg)221 createWithGeneratedName(char *prefix, char *nameBuffer, CreateFunc func, void *arg)
222 {
223 jint error;
224 jint i = 0;
225
226 do {
227 strcpy(nameBuffer, prefix);
228 if (i > 0) {
229 char buf[10];
230 sprintf(buf, ".%d", i+1);
231 strcat(nameBuffer, buf);
232 }
233 error = func(nameBuffer, arg);
234 i++;
235 } while ((error == SYS_INUSE) && (i < MAX_GENERATION_RETRIES));
236
237 if (error != SYS_OK) {
238 setLastError(error);
239 }
240
241 return error;
242 }
243
244 typedef struct SharedMemoryArg {
245 jint size;
246 sys_shmem_t memory;
247 void *start;
248 } SharedMemoryArg;
249
250 static jint
createSharedMem(char * name,void * ptr)251 createSharedMem(char *name, void *ptr)
252 {
253 SharedMemoryArg *arg = ptr;
254 return sysSharedMemCreate(name, arg->size, &arg->memory, &arg->start);
255 }
256
257 static jint
createMutex(char * name,void * arg)258 createMutex(char *name, void *arg)
259 {
260 sys_ipmutex_t *retArg = arg;
261 return sysIPMutexCreate(name, retArg);
262 }
263
264 /*
265 * Creates named or unnamed event that is automatically reset
266 * (in other words, no need to reset event after it has signalled
267 * a thread).
268 */
269 static jint
createEvent(char * name,void * arg)270 createEvent(char *name, void *arg)
271 {
272 sys_event_t *retArg = arg;
273 return sysEventCreate(name, retArg, JNI_FALSE);
274 }
275
276 #define ADD_OFFSET(o1, o2) ((o1 + o2) % SHARED_BUFFER_SIZE)
277 #define FULL(stream) (stream->shared->isFull)
278 #define EMPTY(stream) ((stream->shared->writeOffset == stream->shared->readOffset) \
279 && !stream->shared->isFull)
280
281 static jint
leaveMutex(Stream * stream)282 leaveMutex(Stream *stream)
283 {
284 return sysIPMutexExit(stream->mutex);
285 }
286
287 /* enter the stream's mutex and (optionally) check for a closed stream */
288 static jint
enterMutex(Stream * stream,sys_event_t event)289 enterMutex(Stream *stream, sys_event_t event)
290 {
291 jint ret = sysIPMutexEnter(stream->mutex, event);
292 if (ret != SYS_OK) {
293 if (IS_STATE_CLOSED(stream->state)) {
294 setLastErrorMsg("stream closed");
295 }
296 return ret;
297 }
298 if (IS_STATE_CLOSED(stream->state)) {
299 setLastErrorMsg("stream closed");
300 (void)leaveMutex(stream);
301 return SYS_ERR;
302 }
303 return SYS_OK;
304 }
305
306 /*
307 * Enter/exit with stream mutex held.
308 * On error, does not hold the stream mutex.
309 */
310 static jint
waitForSpace(SharedMemoryConnection * connection,Stream * stream)311 waitForSpace(SharedMemoryConnection *connection, Stream *stream)
312 {
313 jint error = SYS_OK;
314
315 /* Assumes mutex is held on call */
316 while ((error == SYS_OK) && FULL(stream)) {
317 CHECK_ERROR(leaveMutex(stream));
318 error = sysEventWait(connection->otherProcess, stream->hasSpace, 0);
319 if (error == SYS_OK) {
320 CHECK_ERROR(enterMutex(stream, connection->shutdown));
321 } else {
322 setLastError(error);
323 }
324 }
325 return error;
326 }
327
328 static jint
signalSpace(Stream * stream)329 signalSpace(Stream *stream)
330 {
331 return sysEventSignal(stream->hasSpace);
332 }
333
334 /*
335 * Enter/exit with stream mutex held.
336 * On error, does not hold the stream mutex.
337 */
338 static jint
waitForData(SharedMemoryConnection * connection,Stream * stream)339 waitForData(SharedMemoryConnection *connection, Stream *stream)
340 {
341 jint error = SYS_OK;
342
343 /* Assumes mutex is held on call */
344 while ((error == SYS_OK) && EMPTY(stream)) {
345 CHECK_ERROR(leaveMutex(stream));
346 error = sysEventWait(connection->otherProcess, stream->hasData, 0);
347 if (error == SYS_OK) {
348 CHECK_ERROR(enterMutex(stream, connection->shutdown));
349 } else {
350 setLastError(error);
351 }
352 }
353 return error;
354 }
355
356 static jint
signalData(Stream * stream)357 signalData(Stream *stream)
358 {
359 return sysEventSignal(stream->hasData);
360 }
361
362
363 static jint
closeStream(Stream * stream,jboolean linger)364 closeStream(Stream *stream, jboolean linger)
365 {
366 /*
367 * Lock stream during close - ignore shutdown event as we are
368 * closing down and shutdown should be signalled.
369 */
370 CHECK_ERROR(enterMutex(stream, NULL));
371
372 /* mark the stream as closed */
373 stream->state = STATE_CLOSED;
374 /* wake up waitForData() if it is in sysEventWait() */
375 sysEventSignal(stream->hasData);
376 sysEventClose(stream->hasData);
377 /* wake up waitForSpace() if it is in sysEventWait() */
378 sysEventSignal(stream->hasSpace);
379 sysEventClose(stream->hasSpace);
380
381 /*
382 * If linger requested then give the stream a few seconds to
383 * drain before closing it.
384 */
385 if (linger) {
386 int attempts = 10;
387 while (!EMPTY(stream) && attempts>0) {
388 CHECK_ERROR(leaveMutex(stream));
389 sysSleep(200);
390 CHECK_ERROR(enterMutex(stream, NULL));
391 attempts--;
392 }
393 }
394
395 CHECK_ERROR(leaveMutex(stream));
396 sysIPMutexClose(stream->mutex);
397 return SYS_OK;
398 }
399
400 /*
401 * Server creates stream.
402 */
403 static int
createStream(char * name,Stream * stream)404 createStream(char *name, Stream *stream)
405 {
406 jint error;
407 char objectName[MAX_IPC_NAME];
408
409 sprintf(objectName, "%s.mutex", name);
410 error = createWithGeneratedName(objectName, stream->shared->mutexName,
411 createMutex, &stream->mutex);
412 if (error != SYS_OK) {
413 return error;
414 }
415
416 sprintf(objectName, "%s.hasData", name);
417 error = createWithGeneratedName(objectName, stream->shared->hasDataEventName,
418 createEvent, &stream->hasData);
419 if (error != SYS_OK) {
420 (void)closeStream(stream, JNI_FALSE);
421 return error;
422 }
423
424 sprintf(objectName, "%s.hasSpace", name);
425 error = createWithGeneratedName(objectName, stream->shared->hasSpaceEventName,
426 createEvent, &stream->hasSpace);
427 if (error != SYS_OK) {
428 (void)closeStream(stream, JNI_FALSE);
429 return error;
430 }
431
432 stream->shared->readOffset = 0;
433 stream->shared->writeOffset = 0;
434 stream->shared->isFull = JNI_FALSE;
435 stream->state = STATE_OPEN;
436 return SYS_OK;
437 }
438
439
440 /*
441 * Initialization for the stream opened by the other process
442 */
443 static int
openStream(Stream * stream)444 openStream(Stream *stream)
445 {
446 jint error;
447
448 CHECK_ERROR(sysIPMutexOpen(stream->shared->mutexName, &stream->mutex));
449
450 error = sysEventOpen(stream->shared->hasDataEventName,
451 &stream->hasData);
452 if (error != SYS_OK) {
453 setLastError(error);
454 (void)closeStream(stream, JNI_FALSE);
455 return error;
456 }
457
458 error = sysEventOpen(stream->shared->hasSpaceEventName,
459 &stream->hasSpace);
460 if (error != SYS_OK) {
461 setLastError(error);
462 (void)closeStream(stream, JNI_FALSE);
463 return error;
464 }
465
466 stream->state = STATE_OPEN;
467
468 return SYS_OK;
469 }
470
471 /********************************************************************/
472
473 static SharedMemoryConnection *
allocConnection(void)474 allocConnection(void)
475 {
476 /*
477 * TO DO: Track all allocated connections for clean shutdown?
478 */
479 SharedMemoryConnection *conn = (*callback->alloc)(sizeof(SharedMemoryConnection));
480 if (conn != NULL) {
481 memset(conn, 0, sizeof(SharedMemoryConnection));
482 }
483 return conn;
484 }
485
486 static void
freeConnection(SharedMemoryConnection * connection)487 freeConnection(SharedMemoryConnection *connection)
488 {
489 (*callback->free)(connection);
490 }
491
492 static void
closeConnection(SharedMemoryConnection * connection)493 closeConnection(SharedMemoryConnection *connection)
494 {
495 /*
496 * Signal all threads accessing this connection that we are
497 * shutting down.
498 */
499 if (connection->shutdown) {
500 sysEventSignal(connection->shutdown);
501 }
502
503
504 (void)closeStream(&connection->outgoing, JNI_TRUE);
505 (void)closeStream(&connection->incoming, JNI_FALSE);
506
507 if (connection->sharedMemory) {
508 sysSharedMemClose(connection->sharedMemory, connection->shared);
509 }
510 if (connection->otherProcess) {
511 sysProcessClose(connection->otherProcess);
512 }
513
514 /*
515 * Ideally we should close the connection->shutdown event and
516 * free the connection structure. However as closing the
517 * connection is asynchronous it means that other threads may
518 * still be accessing the connection structure. On Win32 this
519 * means we leak 132 bytes and one event per connection. This
520 * memory will be reclaim at process exit.
521 *
522 * if (connection->shutdown)
523 * sysEventClose(connection->shutdown);
524 * freeConnection(connection);
525 */
526 }
527
528
529 /*
530 * For client: connect to the shared memory. Open incoming and
531 * outgoing streams.
532 */
533 static jint
openConnection(SharedMemoryTransport * transport,jlong otherPID,SharedMemoryConnection ** connectionPtr)534 openConnection(SharedMemoryTransport *transport, jlong otherPID,
535 SharedMemoryConnection **connectionPtr)
536 {
537 jint error;
538
539 SharedMemoryConnection *connection = allocConnection();
540 if (connection == NULL) {
541 return SYS_NOMEM;
542 }
543
544 sprintf(connection->name, "%s.%" PRId64, transport->name, sysProcessGetID());
545 error = sysSharedMemOpen(connection->name, &connection->sharedMemory,
546 &connection->shared);
547 if (error != SYS_OK) {
548 closeConnection(connection);
549 return error;
550 }
551
552 /* This process is the client */
553 connection->incoming.shared = &connection->shared->toClient;
554 connection->outgoing.shared = &connection->shared->toServer;
555
556 error = openStream(&connection->incoming);
557 if (error != SYS_OK) {
558 closeConnection(connection);
559 return error;
560 }
561
562 error = openStream(&connection->outgoing);
563 if (error != SYS_OK) {
564 closeConnection(connection);
565 return error;
566 }
567
568 error = sysProcessOpen(otherPID, &connection->otherProcess);
569 if (error != SYS_OK) {
570 setLastError(error);
571 closeConnection(connection);
572 return error;
573 }
574
575 /*
576 * Create an event that signals that the connection is shutting
577 * down. The event is unnamed as it's process local, and is
578 * manually reset (so that signalling the event will signal
579 * all threads waiting on it).
580 */
581 error = sysEventCreate(NULL, &connection->shutdown, JNI_TRUE);
582 if (error != SYS_OK) {
583 setLastError(error);
584 closeConnection(connection);
585 return error;
586 }
587
588 *connectionPtr = connection;
589 return SYS_OK;
590 }
591
592 /*
593 * For server: create the shared memory. Create incoming and
594 * outgoing streams.
595 */
596 static jint
createConnection(SharedMemoryTransport * transport,jlong otherPID,SharedMemoryConnection ** connectionPtr)597 createConnection(SharedMemoryTransport *transport, jlong otherPID,
598 SharedMemoryConnection **connectionPtr)
599 {
600 jint error;
601 char streamName[MAX_IPC_NAME];
602
603 SharedMemoryConnection *connection = allocConnection();
604 if (connection == NULL) {
605 return SYS_NOMEM;
606 }
607
608 sprintf(connection->name, "%s.%" PRId64, transport->name, otherPID);
609 error = sysSharedMemCreate(connection->name, sizeof(SharedMemory),
610 &connection->sharedMemory, &connection->shared);
611 if (error != SYS_OK) {
612 closeConnection(connection);
613 return error;
614 }
615
616 memset(connection->shared, 0, sizeof(SharedMemory));
617
618 /* This process is the server */
619 connection->incoming.shared = &connection->shared->toServer;
620 connection->outgoing.shared = &connection->shared->toClient;
621
622 strcpy(streamName, connection->name);
623 strcat(streamName, ".ctos");
624 error = createStream(streamName, &connection->incoming);
625 if (error != SYS_OK) {
626 closeConnection(connection);
627 return error;
628 }
629
630 strcpy(streamName, connection->name);
631 strcat(streamName, ".stoc");
632 error = createStream(streamName, &connection->outgoing);
633 if (error != SYS_OK) {
634 closeConnection(connection);
635 return error;
636 }
637
638 error = sysProcessOpen(otherPID, &connection->otherProcess);
639 if (error != SYS_OK) {
640 setLastError(error);
641 closeConnection(connection);
642 return error;
643 }
644
645 /*
646 * Create an event that signals that the connection is shutting
647 * down. The event is unnamed as it's process local, and is
648 * manually reset (so that a signalling the event will signal
649 * all threads waiting on it).
650 */
651 error = sysEventCreate(NULL, &connection->shutdown, JNI_TRUE);
652 if (error != SYS_OK) {
653 setLastError(error);
654 closeConnection(connection);
655 return error;
656 }
657
658 *connectionPtr = connection;
659 return SYS_OK;
660 }
661
662 /********************************************************************/
663
664 static SharedMemoryTransport *
allocTransport(void)665 allocTransport(void)
666 {
667 /*
668 * TO DO: Track all allocated transports for clean shutdown?
669 */
670 return (*callback->alloc)(sizeof(SharedMemoryTransport));
671 }
672
673 static void
freeTransport(SharedMemoryTransport * transport)674 freeTransport(SharedMemoryTransport *transport)
675 {
676 (*callback->free)(transport);
677 }
678
679 static void
closeTransport(SharedMemoryTransport * transport)680 closeTransport(SharedMemoryTransport *transport)
681 {
682 sysIPMutexClose(transport->mutex);
683 sysEventClose(transport->acceptEvent);
684 sysEventClose(transport->attachEvent);
685 sysSharedMemClose(transport->sharedMemory, transport->shared);
686 freeTransport(transport);
687 }
688
689 static int
openTransport(const char * address,SharedMemoryTransport ** transportPtr)690 openTransport(const char *address, SharedMemoryTransport **transportPtr)
691 {
692 jint error;
693 SharedMemoryTransport *transport;
694
695 transport = allocTransport();
696 if (transport == NULL) {
697 return SYS_NOMEM;
698 }
699 memset(transport, 0, sizeof(*transport));
700
701 if (strlen(address) >= MAX_IPC_PREFIX) {
702 char buf[128];
703 sprintf(buf, "Error: address strings longer than %d characters are invalid\n", MAX_IPC_PREFIX);
704 setLastErrorMsg(buf);
705 closeTransport(transport);
706 return SYS_ERR;
707 }
708
709 error = sysSharedMemOpen(address, &transport->sharedMemory, &transport->shared);
710 if (error != SYS_OK) {
711 setLastError(error);
712 closeTransport(transport);
713 return error;
714 }
715 strcpy(transport->name, address);
716
717 error = sysIPMutexOpen(transport->shared->mutexName, &transport->mutex);
718 if (error != SYS_OK) {
719 setLastError(error);
720 closeTransport(transport);
721 return error;
722 }
723
724 error = sysEventOpen(transport->shared->acceptEventName,
725 &transport->acceptEvent);
726 if (error != SYS_OK) {
727 setLastError(error);
728 closeTransport(transport);
729 return error;
730 }
731
732 error = sysEventOpen(transport->shared->attachEventName,
733 &transport->attachEvent);
734 if (error != SYS_OK) {
735 setLastError(error);
736 closeTransport(transport);
737 return error;
738 }
739
740 *transportPtr = transport;
741 return SYS_OK;
742 }
743
744 static jint
createTransport(const char * address,SharedMemoryTransport ** transportPtr)745 createTransport(const char *address, SharedMemoryTransport **transportPtr)
746 {
747 SharedMemoryTransport *transport;
748 jint error;
749 char objectName[MAX_IPC_NAME];
750
751 transport = allocTransport();
752 if (transport == NULL) {
753 return SYS_NOMEM;
754 }
755 memset(transport, 0, sizeof(*transport));
756
757 if ((address == NULL) || (address[0] == '\0')) {
758 SharedMemoryArg arg;
759 arg.size = sizeof(SharedListener);
760 error = createWithGeneratedName("javadebug", transport->name,
761 createSharedMem, &arg);
762 transport->shared = arg.start;
763 transport->sharedMemory = arg.memory;
764 } else {
765 if (strlen(address) >= MAX_IPC_PREFIX) {
766 char buf[128];
767 sprintf(buf, "Error: address strings longer than %d characters are invalid\n", MAX_IPC_PREFIX);
768 setLastErrorMsg(buf);
769 closeTransport(transport);
770 return SYS_ERR;
771 }
772 strcpy(transport->name, address);
773 error = sysSharedMemCreate(address, sizeof(SharedListener),
774 &transport->sharedMemory, &transport->shared);
775 }
776 if (error != SYS_OK) {
777 setLastError(error);
778 closeTransport(transport);
779 return error;
780 }
781
782 memset(transport->shared, 0, sizeof(SharedListener));
783 transport->shared->acceptingPID = sysProcessGetID();
784
785 sprintf(objectName, "%s.mutex", transport->name);
786 error = createWithGeneratedName(objectName, transport->shared->mutexName,
787 createMutex, &transport->mutex);
788 if (error != SYS_OK) {
789 closeTransport(transport);
790 return error;
791 }
792
793 sprintf(objectName, "%s.accept", transport->name);
794 error = createWithGeneratedName(objectName, transport->shared->acceptEventName,
795 createEvent, &transport->acceptEvent);
796 if (error != SYS_OK) {
797 closeTransport(transport);
798 return error;
799 }
800
801 sprintf(objectName, "%s.attach", transport->name);
802 error = createWithGeneratedName(objectName, transport->shared->attachEventName,
803 createEvent, &transport->attachEvent);
804 if (error != SYS_OK) {
805 closeTransport(transport);
806 return error;
807 }
808
809 *transportPtr = transport;
810 return SYS_OK;
811 }
812
813
814 jint
shmemBase_listen(const char * address,SharedMemoryTransport ** transportPtr)815 shmemBase_listen(const char *address, SharedMemoryTransport **transportPtr)
816 {
817 int error;
818
819 clearLastError();
820
821 error = createTransport(address, transportPtr);
822 if (error == SYS_OK) {
823 (*transportPtr)->shared->isListening = JNI_TRUE;
824 }
825 return error;
826 }
827
828
829 jint
shmemBase_accept(SharedMemoryTransport * transport,long timeout,SharedMemoryConnection ** connectionPtr)830 shmemBase_accept(SharedMemoryTransport *transport,
831 long timeout,
832 SharedMemoryConnection **connectionPtr)
833 {
834 jint error;
835 SharedMemoryConnection *connection;
836
837 clearLastError();
838
839 CHECK_ERROR(sysEventWait(NULL, transport->attachEvent, timeout));
840
841 error = createConnection(transport, transport->shared->attachingPID,
842 &connection);
843 if (error != SYS_OK) {
844 /*
845 * Reject the attacher
846 */
847 transport->shared->isAccepted = JNI_FALSE;
848 sysEventSignal(transport->acceptEvent);
849
850 freeConnection(connection);
851 return error;
852 }
853
854 transport->shared->isAccepted = JNI_TRUE;
855 error = sysEventSignal(transport->acceptEvent);
856 if (error != SYS_OK) {
857 /*
858 * No real point trying to reject it.
859 */
860 closeConnection(connection);
861 return error;
862 }
863
864 *connectionPtr = connection;
865 return SYS_OK;
866 }
867
868 static jint
doAttach(SharedMemoryTransport * transport,long timeout)869 doAttach(SharedMemoryTransport *transport, long timeout)
870 {
871 transport->shared->attachingPID = sysProcessGetID();
872 CHECK_ERROR(sysEventSignal(transport->attachEvent));
873 CHECK_ERROR(sysEventWait(NULL, transport->acceptEvent, timeout));
874 return SYS_OK;
875 }
876
877 jint
shmemBase_attach(const char * addressString,long timeout,SharedMemoryConnection ** connectionPtr)878 shmemBase_attach(const char *addressString, long timeout, SharedMemoryConnection **connectionPtr)
879 {
880 int error;
881 SharedMemoryTransport *transport;
882 jlong acceptingPID;
883
884 clearLastError();
885
886 error = openTransport(addressString, &transport);
887 if (error != SYS_OK) {
888 return error;
889 }
890
891 /* lock transport - no additional event to wait on as no connection yet */
892 error = sysIPMutexEnter(transport->mutex, NULL);
893 if (error != SYS_OK) {
894 setLastError(error);
895 closeTransport(transport);
896 return error;
897 }
898
899 if (transport->shared->isListening) {
900 error = doAttach(transport, timeout);
901 if (error == SYS_OK) {
902 acceptingPID = transport->shared->acceptingPID;
903 }
904 } else {
905 /* Not listening: error */
906 error = SYS_ERR;
907 }
908
909 sysIPMutexExit(transport->mutex);
910 if (error != SYS_OK) {
911 closeTransport(transport);
912 return error;
913 }
914
915 error = openConnection(transport, acceptingPID, connectionPtr);
916
917 closeTransport(transport);
918
919 return error;
920 }
921
922
923
924
925 void
shmemBase_closeConnection(SharedMemoryConnection * connection)926 shmemBase_closeConnection(SharedMemoryConnection *connection)
927 {
928 clearLastError();
929 closeConnection(connection);
930 }
931
932 void
shmemBase_closeTransport(SharedMemoryTransport * transport)933 shmemBase_closeTransport(SharedMemoryTransport *transport)
934 {
935 clearLastError();
936 closeTransport(transport);
937 }
938
939 jint
shmemBase_sendByte(SharedMemoryConnection * connection,jbyte data)940 shmemBase_sendByte(SharedMemoryConnection *connection, jbyte data)
941 {
942 Stream *stream = &connection->outgoing;
943 SharedStream *shared = stream->shared;
944 int offset;
945
946 clearLastError();
947
948 CHECK_ERROR(enterMutex(stream, connection->shutdown));
949 CHECK_ERROR(waitForSpace(connection, stream));
950 SHMEM_ASSERT(!FULL(stream));
951 offset = shared->writeOffset;
952 shared->buffer[offset] = data;
953 shared->writeOffset = ADD_OFFSET(offset, 1);
954 shared->isFull = (shared->readOffset == shared->writeOffset);
955
956 STREAM_INVARIANT(stream);
957 CHECK_ERROR(leaveMutex(stream));
958
959 CHECK_ERROR(signalData(stream));
960
961 return SYS_OK;
962 }
963
964 jint
shmemBase_receiveByte(SharedMemoryConnection * connection,jbyte * data)965 shmemBase_receiveByte(SharedMemoryConnection *connection, jbyte *data)
966 {
967 Stream *stream = &connection->incoming;
968 SharedStream *shared = stream->shared;
969 int offset;
970
971 clearLastError();
972
973 CHECK_ERROR(enterMutex(stream, connection->shutdown));
974 CHECK_ERROR(waitForData(connection, stream));
975 SHMEM_ASSERT(!EMPTY(stream));
976 offset = shared->readOffset;
977 *data = shared->buffer[offset];
978 shared->readOffset = ADD_OFFSET(offset, 1);
979 shared->isFull = JNI_FALSE;
980
981 STREAM_INVARIANT(stream);
982 CHECK_ERROR(leaveMutex(stream));
983
984 CHECK_ERROR(signalSpace(stream));
985
986 return SYS_OK;
987 }
988
989 static jint
sendBytes(SharedMemoryConnection * connection,const void * bytes,jint length)990 sendBytes(SharedMemoryConnection *connection, const void *bytes, jint length)
991 {
992 Stream *stream = &connection->outgoing;
993 SharedStream *shared = stream->shared;
994 jint fragmentStart;
995 jint fragmentLength;
996 jint index = 0;
997 jint maxLength;
998
999 clearLastError();
1000
1001 CHECK_ERROR(enterMutex(stream, connection->shutdown));
1002 while (index < length) {
1003 CHECK_ERROR(waitForSpace(connection, stream));
1004 SHMEM_ASSERT(!FULL(stream));
1005
1006 fragmentStart = shared->writeOffset;
1007
1008 if (fragmentStart < shared->readOffset) {
1009 maxLength = shared->readOffset - fragmentStart;
1010 } else {
1011 maxLength = SHARED_BUFFER_SIZE - fragmentStart;
1012 }
1013 fragmentLength = MIN(maxLength, length - index);
1014 memcpy(shared->buffer + fragmentStart, (jbyte *)bytes + index, fragmentLength);
1015 shared->writeOffset = ADD_OFFSET(fragmentStart, fragmentLength);
1016 index += fragmentLength;
1017
1018 shared->isFull = (shared->readOffset == shared->writeOffset);
1019
1020 STREAM_INVARIANT(stream);
1021 CHECK_ERROR(signalData(stream));
1022
1023 }
1024 CHECK_ERROR(leaveMutex(stream));
1025
1026 return SYS_OK;
1027 }
1028
1029
1030 /*
1031 * Send packet header followed by data.
1032 */
1033 jint
shmemBase_sendPacket(SharedMemoryConnection * connection,const jdwpPacket * packet)1034 shmemBase_sendPacket(SharedMemoryConnection *connection, const jdwpPacket *packet)
1035 {
1036 jint data_length;
1037
1038 clearLastError();
1039
1040 CHECK_ERROR(sendBytes(connection, &packet->type.cmd.id, sizeof(jint)));
1041 CHECK_ERROR(sendBytes(connection, &packet->type.cmd.flags, sizeof(jbyte)));
1042
1043 if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1044 CHECK_ERROR(sendBytes(connection, &packet->type.reply.errorCode, sizeof(jshort)));
1045 } else {
1046 CHECK_ERROR(sendBytes(connection, &packet->type.cmd.cmdSet, sizeof(jbyte)));
1047 CHECK_ERROR(sendBytes(connection, &packet->type.cmd.cmd, sizeof(jbyte)));
1048 }
1049
1050 data_length = packet->type.cmd.len - JDWP_HEADER_SIZE;
1051 SHMEM_GUARANTEE(data_length >= 0);
1052 CHECK_ERROR(sendBytes(connection, &data_length, sizeof(jint)));
1053
1054 if (data_length > 0) {
1055 CHECK_ERROR(sendBytes(connection, packet->type.cmd.data, data_length));
1056 }
1057
1058 return SYS_OK;
1059 }
1060
1061 static jint
receiveBytes(SharedMemoryConnection * connection,void * bytes,jint length)1062 receiveBytes(SharedMemoryConnection *connection, void *bytes, jint length)
1063 {
1064 Stream *stream = &connection->incoming;
1065 SharedStream *shared = stream->shared;
1066 jint fragmentStart;
1067 jint fragmentLength;
1068 jint index = 0;
1069 jint maxLength;
1070
1071 clearLastError();
1072
1073 CHECK_ERROR(enterMutex(stream, connection->shutdown));
1074 while (index < length) {
1075 CHECK_ERROR(waitForData(connection, stream));
1076 SHMEM_ASSERT(!EMPTY(stream));
1077
1078 fragmentStart = shared->readOffset;
1079 if (fragmentStart < shared->writeOffset) {
1080 maxLength = shared->writeOffset - fragmentStart;
1081 } else {
1082 maxLength = SHARED_BUFFER_SIZE - fragmentStart;
1083 }
1084 fragmentLength = MIN(maxLength, length - index);
1085 memcpy((jbyte *)bytes + index, shared->buffer + fragmentStart, fragmentLength);
1086 shared->readOffset = ADD_OFFSET(fragmentStart, fragmentLength);
1087 index += fragmentLength;
1088
1089 shared->isFull = JNI_FALSE;
1090
1091 STREAM_INVARIANT(stream);
1092 CHECK_ERROR(signalSpace(stream));
1093 }
1094 CHECK_ERROR(leaveMutex(stream));
1095
1096 return SYS_OK;
1097 }
1098
1099 /*
1100 * Read packet header and insert into packet structure.
1101 * Allocate space for the data and fill it in.
1102 */
1103 jint
shmemBase_receivePacket(SharedMemoryConnection * connection,jdwpPacket * packet)1104 shmemBase_receivePacket(SharedMemoryConnection *connection, jdwpPacket *packet)
1105 {
1106 jint data_length;
1107 jint error;
1108
1109 clearLastError();
1110
1111 CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.id, sizeof(jint)));
1112 CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.flags, sizeof(jbyte)));
1113
1114 if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1115 CHECK_ERROR(receiveBytes(connection, &packet->type.reply.errorCode, sizeof(jshort)));
1116 } else {
1117 CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.cmdSet, sizeof(jbyte)));
1118 CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.cmd, sizeof(jbyte)));
1119 }
1120
1121 CHECK_ERROR(receiveBytes(connection, &data_length, sizeof(jint)));
1122
1123 if (data_length < 0) {
1124 return SYS_ERR;
1125 } else if (data_length == 0) {
1126 packet->type.cmd.len = JDWP_HEADER_SIZE;
1127 packet->type.cmd.data = NULL;
1128 } else {
1129 packet->type.cmd.len = data_length + JDWP_HEADER_SIZE;
1130 packet->type.cmd.data = (*callback->alloc)(data_length);
1131 if (packet->type.cmd.data == NULL) {
1132 return SYS_ERR;
1133 }
1134
1135 error = receiveBytes(connection, packet->type.cmd.data, data_length);
1136 if (error != SYS_OK) {
1137 (*callback->free)(packet->type.cmd.data);
1138 return error;
1139 }
1140 }
1141
1142 return SYS_OK;
1143 }
1144
1145 jint
shmemBase_name(struct SharedMemoryTransport * transport,char ** name)1146 shmemBase_name(struct SharedMemoryTransport *transport, char **name)
1147 {
1148 *name = transport->name;
1149 return SYS_OK;
1150 }
1151
1152 jint
shmemBase_getlasterror(char * msg,jint size)1153 shmemBase_getlasterror(char *msg, jint size) {
1154 char *errstr = (char *)sysTlsGet(tlsIndex);
1155 if (errstr != NULL) {
1156 strcpy(msg, errstr);
1157 return SYS_OK;
1158 } else {
1159 return SYS_ERR;
1160 }
1161 }
1162
1163
1164 void
exitTransportWithError(char * message,char * fileName,char * date,int lineNumber)1165 exitTransportWithError(char *message, char *fileName,
1166 char *date, int lineNumber)
1167 {
1168 JNIEnv *env;
1169 jint error;
1170 char buffer[500];
1171
1172 sprintf(buffer, "Shared Memory Transport \"%s\" (%s), line %d: %s\n",
1173 fileName, date, lineNumber, message);
1174 error = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2);
1175 if (error != JNI_OK) {
1176 /*
1177 * We're forced into a direct call to exit()
1178 */
1179 fprintf(stderr, "%s", buffer);
1180 exit(-1);
1181 } else {
1182 (*env)->FatalError(env, buffer);
1183 }
1184 }
1185