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 }