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