author | ohair |
Fri, 22 Aug 2008 12:24:27 -0700 | |
changeset 1090 | c5805b1672a6 |
parent 896 | 5c02031316bf |
child 1247 | b4c26443dee5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
2 |
* Copyright 1998-2005 Sun Microsystems, Inc. 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. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
#include "util.h" |
|
27 |
#include "transport.h" |
|
28 |
#include "debugLoop.h" |
|
29 |
#include "sys.h" |
|
30 |
||
31 |
static jdwpTransportEnv *transport; |
|
32 |
static jrawMonitorID listenerLock; |
|
33 |
static jrawMonitorID sendLock; |
|
34 |
||
35 |
/* |
|
36 |
* data structure used for passing transport info from thread to thread |
|
37 |
*/ |
|
38 |
typedef struct TransportInfo { |
|
39 |
char *name; |
|
40 |
jdwpTransportEnv *transport; |
|
41 |
char *address; |
|
42 |
long timeout; |
|
43 |
} TransportInfo; |
|
44 |
||
45 |
static struct jdwpTransportCallback callback = {jvmtiAllocate, jvmtiDeallocate}; |
|
46 |
||
47 |
/* |
|
48 |
* Print the last transport error |
|
49 |
*/ |
|
50 |
static void |
|
51 |
printLastError(jdwpTransportEnv *t, jdwpTransportError err) |
|
52 |
{ |
|
53 |
char *msg; |
|
54 |
jbyte *utf8msg; |
|
55 |
jdwpTransportError rv; |
|
56 |
||
57 |
msg = NULL; |
|
58 |
utf8msg = NULL; |
|
59 |
rv = (*t)->GetLastError(t, &msg); /* This is a platform encoded string */ |
|
60 |
if ( msg != NULL ) { |
|
61 |
int len; |
|
62 |
int maxlen; |
|
63 |
||
64 |
/* Convert this string to UTF8 */ |
|
65 |
len = (int)strlen(msg); |
|
66 |
maxlen = len+len/2+2; /* Should allow for plenty of room */ |
|
67 |
utf8msg = (jbyte*)jvmtiAllocate(maxlen+1); |
|
68 |
(void)(gdata->npt->utf8FromPlatform)(gdata->npt->utf, |
|
69 |
msg, len, utf8msg, maxlen); |
|
70 |
utf8msg[maxlen] = 0; |
|
71 |
} |
|
72 |
if (rv == JDWPTRANSPORT_ERROR_NONE) { |
|
73 |
ERROR_MESSAGE(("transport error %d: %s",err, utf8msg)); |
|
74 |
} else if ( msg!=NULL ) { |
|
75 |
ERROR_MESSAGE(("transport error %d: %s",err, utf8msg)); |
|
76 |
} else { |
|
77 |
ERROR_MESSAGE(("transport error %d: %s",err, "UNKNOWN")); |
|
78 |
} |
|
79 |
jvmtiDeallocate(msg); |
|
80 |
jvmtiDeallocate(utf8msg); |
|
81 |
} |
|
82 |
||
83 |
/* Find OnLoad symbol */ |
|
84 |
static jdwpTransport_OnLoad_t |
|
85 |
findTransportOnLoad(void *handle) |
|
86 |
{ |
|
87 |
jdwpTransport_OnLoad_t onLoad; |
|
88 |
||
89 |
onLoad = (jdwpTransport_OnLoad_t)NULL; |
|
90 |
if (handle == NULL) { |
|
91 |
return onLoad; |
|
92 |
} |
|
93 |
onLoad = (jdwpTransport_OnLoad_t) |
|
94 |
dbgsysFindLibraryEntry(handle, "jdwpTransport_OnLoad"); |
|
95 |
return onLoad; |
|
96 |
} |
|
97 |
||
98 |
/* Load transport library (directory=="" means do system search) */ |
|
99 |
static void * |
|
100 |
loadTransportLibrary(char *libdir, char *name) |
|
101 |
{ |
|
102 |
void *handle; |
|
103 |
char libname[MAXPATHLEN+2]; |
|
104 |
char buf[MAXPATHLEN*2+100]; |
|
105 |
char *plibdir; |
|
106 |
||
107 |
/* Convert libdir from UTF-8 to platform encoding */ |
|
108 |
plibdir = NULL; |
|
109 |
if ( libdir != NULL ) { |
|
110 |
int len; |
|
111 |
||
112 |
len = (int)strlen(libdir); |
|
113 |
(void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf, |
|
114 |
(jbyte*)libdir, len, buf, (int)sizeof(buf)); |
|
115 |
plibdir = buf; |
|
116 |
} |
|
117 |
||
118 |
/* Construct library name (simple name or full path) */ |
|
119 |
dbgsysBuildLibName(libname, sizeof(libname), plibdir, name); |
|
120 |
||
121 |
/* dlopen (unix) / LoadLibrary (windows) the transport library */ |
|
122 |
handle = dbgsysLoadLibrary(libname, buf, sizeof(buf)); |
|
123 |
return handle; |
|
124 |
} |
|
125 |
||
126 |
/* |
|
127 |
* loadTransport() is adapted from loadJVMHelperLib() in |
|
128 |
* JDK 1.2 javai.c v1.61 |
|
129 |
*/ |
|
130 |
static jdwpError |
|
131 |
loadTransport(char *name, jdwpTransportEnv **transportPtr) |
|
132 |
{ |
|
133 |
JNIEnv *env; |
|
134 |
jdwpTransport_OnLoad_t onLoad; |
|
135 |
void *handle; |
|
136 |
char *libdir; |
|
137 |
||
138 |
/* Make sure library name is not empty */ |
|
139 |
if (name == NULL) { |
|
140 |
ERROR_MESSAGE(("library name is empty")); |
|
141 |
return JDWP_ERROR(TRANSPORT_LOAD); |
|
142 |
} |
|
143 |
||
144 |
/* First, look in sun.boot.library.path. This should find the standard |
|
145 |
* dt_socket and dt_shmem transport libraries, or any library |
|
146 |
* that was delivered with the J2SE. |
|
147 |
* Note: Java property sun.boot.library.path contains a single directory. |
|
148 |
*/ |
|
149 |
libdir = gdata->property_sun_boot_library_path; |
|
150 |
if (libdir == NULL) { |
|
151 |
ERROR_MESSAGE(("Java property sun.boot.library.path is not set")); |
|
152 |
return JDWP_ERROR(TRANSPORT_LOAD); |
|
153 |
} |
|
154 |
handle = loadTransportLibrary(libdir, name); |
|
155 |
if (handle == NULL) { |
|
156 |
/* Second, look along the path used by the native dlopen/LoadLibrary |
|
157 |
* functions. This should effectively try and load the simple |
|
158 |
* library name, which will cause the default system library |
|
159 |
* search technique to happen. |
|
160 |
* We should only reach here if the transport library wasn't found |
|
161 |
* in the J2SE directory, e.g. it's a custom transport library |
|
162 |
* not installed in the J2SE like dt_socket and dt_shmem is. |
|
163 |
* |
|
164 |
* Note: Why not use java.library.path? Several reasons: |
|
165 |
* a) This matches existing agentlib search |
|
166 |
* b) These are technically not JNI libraries |
|
167 |
*/ |
|
168 |
handle = loadTransportLibrary("", name); |
|
169 |
} |
|
170 |
||
171 |
/* See if a library was found with this name */ |
|
172 |
if (handle == NULL) { |
|
173 |
ERROR_MESSAGE(("transport library not found: %s", name)); |
|
174 |
return JDWP_ERROR(TRANSPORT_LOAD); |
|
175 |
} |
|
176 |
||
177 |
/* Find the onLoad address */ |
|
178 |
onLoad = findTransportOnLoad(handle); |
|
179 |
if (onLoad == NULL) { |
|
180 |
ERROR_MESSAGE(("transport library missing onLoad entry: %s", name)); |
|
181 |
return JDWP_ERROR(TRANSPORT_LOAD); |
|
182 |
} |
|
183 |
||
184 |
/* Get transport interface */ |
|
185 |
env = getEnv(); |
|
186 |
if ( env != NULL ) { |
|
187 |
jdwpTransportEnv *t; |
|
188 |
JavaVM *jvm; |
|
189 |
jint ver; |
|
190 |
||
191 |
JNI_FUNC_PTR(env,GetJavaVM)(env, &jvm); |
|
192 |
ver = (*onLoad)(jvm, &callback, JDWPTRANSPORT_VERSION_1_0, &t); |
|
193 |
if (ver != JNI_OK) { |
|
194 |
switch (ver) { |
|
195 |
case JNI_ENOMEM : |
|
196 |
ERROR_MESSAGE(("insufficient memory to complete initialization")); |
|
197 |
break; |
|
198 |
||
199 |
case JNI_EVERSION : |
|
200 |
ERROR_MESSAGE(("transport doesn't recognize version %x", |
|
201 |
JDWPTRANSPORT_VERSION_1_0)); |
|
202 |
break; |
|
203 |
||
204 |
case JNI_EEXIST : |
|
205 |
ERROR_MESSAGE(("transport doesn't support multiple environments")); |
|
206 |
break; |
|
207 |
||
208 |
default: |
|
209 |
ERROR_MESSAGE(("unrecognized error %d from transport", ver)); |
|
210 |
break; |
|
211 |
} |
|
212 |
||
213 |
return JDWP_ERROR(TRANSPORT_INIT); |
|
214 |
} |
|
215 |
*transportPtr = t; |
|
216 |
} else { |
|
217 |
return JDWP_ERROR(TRANSPORT_LOAD); |
|
218 |
} |
|
219 |
||
220 |
return JDWP_ERROR(NONE); |
|
221 |
} |
|
222 |
||
223 |
static void |
|
224 |
connectionInitiated(jdwpTransportEnv *t) |
|
225 |
{ |
|
226 |
jint isValid = JNI_FALSE; |
|
227 |
||
228 |
debugMonitorEnter(listenerLock); |
|
229 |
||
230 |
/* |
|
231 |
* Don't allow a connection until initialization is complete |
|
232 |
*/ |
|
233 |
debugInit_waitInitComplete(); |
|
234 |
||
235 |
/* Are we the first transport to get a connection? */ |
|
236 |
||
237 |
if (transport == NULL) { |
|
238 |
transport = t; |
|
239 |
isValid = JNI_TRUE; |
|
240 |
} else { |
|
241 |
if (transport == t) { |
|
242 |
/* connected with the same transport as before */ |
|
243 |
isValid = JNI_TRUE; |
|
244 |
} else { |
|
245 |
/* |
|
246 |
* Another transport got a connection - multiple transports |
|
247 |
* not fully supported yet so shouldn't get here. |
|
248 |
*/ |
|
249 |
(*t)->Close(t); |
|
250 |
JDI_ASSERT(JNI_FALSE); |
|
251 |
} |
|
252 |
} |
|
253 |
||
254 |
if (isValid) { |
|
255 |
debugMonitorNotifyAll(listenerLock); |
|
256 |
} |
|
257 |
||
258 |
debugMonitorExit(listenerLock); |
|
259 |
||
260 |
if (isValid) { |
|
261 |
debugLoop_run(); |
|
262 |
} |
|
263 |
||
264 |
} |
|
265 |
||
266 |
/* |
|
267 |
* Set the transport property (sun.jdwp.listenerAddress) to the |
|
268 |
* specified value. |
|
269 |
*/ |
|
270 |
static void |
|
271 |
setTransportProperty(JNIEnv* env, char* value) { |
|
272 |
char* prop_value = (value == NULL) ? "" : value; |
|
273 |
setAgentPropertyValue(env, "sun.jdwp.listenerAddress", prop_value); |
|
274 |
} |
|
275 |
||
276 |
void |
|
277 |
transport_waitForConnection(void) |
|
278 |
{ |
|
279 |
/* |
|
280 |
* If the VM is suspended on debugger initialization, we wait |
|
281 |
* for a connection before continuing. This ensures that all |
|
282 |
* events are delivered to the debugger. (We might as well do this |
|
283 |
* this since the VM won't continue until a remote debugger attaches |
|
284 |
* and resumes it.) If not suspending on initialization, we must |
|
285 |
* just drop any packets (i.e. events) so that the VM can continue |
|
286 |
* to run. The debugger may not attach until much later. |
|
287 |
*/ |
|
288 |
if (debugInit_suspendOnInit()) { |
|
289 |
debugMonitorEnter(listenerLock); |
|
290 |
while (transport == NULL) { |
|
291 |
debugMonitorWait(listenerLock); |
|
292 |
} |
|
293 |
debugMonitorExit(listenerLock); |
|
294 |
} |
|
295 |
} |
|
296 |
||
297 |
static void JNICALL |
|
298 |
acceptThread(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) |
|
299 |
{ |
|
300 |
TransportInfo *info; |
|
301 |
jdwpTransportEnv *t; |
|
302 |
jdwpTransportError rc; |
|
303 |
||
304 |
LOG_MISC(("Begin accept thread")); |
|
305 |
||
306 |
info = (TransportInfo*)(void*)arg; |
|
307 |
t = info->transport; |
|
308 |
||
309 |
rc = (*t)->Accept(t, info->timeout, 0); |
|
310 |
||
311 |
/* System property no longer needed */ |
|
312 |
setTransportProperty(jni_env, NULL); |
|
313 |
||
314 |
if (rc != JDWPTRANSPORT_ERROR_NONE) { |
|
315 |
/* |
|
316 |
* If accept fails it probably means a timeout, or another fatal error |
|
317 |
* We thus exit the VM after stopping the listener. |
|
318 |
*/ |
|
319 |
printLastError(t, rc); |
|
320 |
(*t)->StopListening(t); |
|
321 |
EXIT_ERROR(JVMTI_ERROR_NONE, "could not connect, timeout or fatal error"); |
|
322 |
} else { |
|
323 |
(*t)->StopListening(t); |
|
324 |
connectionInitiated(t); |
|
325 |
} |
|
326 |
||
327 |
LOG_MISC(("End accept thread")); |
|
328 |
} |
|
329 |
||
330 |
static void JNICALL |
|
331 |
attachThread(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) |
|
332 |
{ |
|
333 |
LOG_MISC(("Begin attach thread")); |
|
334 |
connectionInitiated((jdwpTransportEnv *)(void*)arg); |
|
335 |
LOG_MISC(("End attach thread")); |
|
336 |
} |
|
337 |
||
338 |
void |
|
339 |
transport_initialize(void) |
|
340 |
{ |
|
341 |
transport = NULL; |
|
342 |
listenerLock = debugMonitorCreate("JDWP Transport Listener Monitor"); |
|
343 |
sendLock = debugMonitorCreate("JDWP Transport Send Monitor"); |
|
344 |
} |
|
345 |
||
346 |
void |
|
347 |
transport_reset(void) |
|
348 |
{ |
|
349 |
/* |
|
350 |
* Reset the transport by closing any listener (will silently fail |
|
351 |
* with JDWPTRANSPORT_ERROR_ILLEGAL_STATE if not listening), and |
|
352 |
* closing any connection (will also fail silently if not |
|
353 |
* connected). |
|
354 |
* |
|
355 |
* Note: There's an assumption here that we don't yet support |
|
356 |
* multiple transports. When we do then we need a clear transition |
|
357 |
* from the current transport to the new transport. |
|
358 |
*/ |
|
359 |
if (transport != NULL) { |
|
360 |
setTransportProperty(getEnv(), NULL); |
|
361 |
(*transport)->StopListening(transport); |
|
362 |
(*transport)->Close(transport); |
|
363 |
} |
|
364 |
} |
|
365 |
||
366 |
static jdwpError |
|
367 |
launch(char *command, char *name, char *address) |
|
368 |
{ |
|
369 |
jint rc; |
|
370 |
char *buf; |
|
371 |
char *commandLine; |
|
372 |
int len; |
|
373 |
||
374 |
/* Construct complete command line (all in UTF-8) */ |
|
375 |
commandLine = jvmtiAllocate((int)strlen(command) + |
|
376 |
(int)strlen(name) + |
|
377 |
(int)strlen(address) + 3); |
|
378 |
if (commandLine == NULL) { |
|
379 |
return JDWP_ERROR(OUT_OF_MEMORY); |
|
380 |
} |
|
381 |
(void)strcpy(commandLine, command); |
|
382 |
(void)strcat(commandLine, " "); |
|
383 |
(void)strcat(commandLine, name); |
|
384 |
(void)strcat(commandLine, " "); |
|
385 |
(void)strcat(commandLine, address); |
|
386 |
||
387 |
/* Convert commandLine from UTF-8 to platform encoding */ |
|
388 |
len = (int)strlen(commandLine); |
|
389 |
buf = jvmtiAllocate(len*3+3); |
|
390 |
(void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf, |
|
391 |
(jbyte*)commandLine, len, buf, len*3+3); |
|
392 |
||
393 |
/* Exec commandLine */ |
|
394 |
rc = dbgsysExec(buf); |
|
395 |
||
396 |
/* Free up buffers */ |
|
397 |
jvmtiDeallocate(buf); |
|
398 |
jvmtiDeallocate(commandLine); |
|
399 |
||
400 |
/* And non-zero exit status means we had an error */ |
|
401 |
if (rc != SYS_OK) { |
|
402 |
return JDWP_ERROR(TRANSPORT_INIT); |
|
403 |
} |
|
404 |
return JDWP_ERROR(NONE); |
|
405 |
} |
|
406 |
||
407 |
jdwpError |
|
408 |
transport_startTransport(jboolean isServer, char *name, char *address, |
|
409 |
long timeout) |
|
410 |
{ |
|
411 |
jvmtiStartFunction func; |
|
412 |
jdwpTransportEnv *trans; |
|
413 |
char threadName[MAXPATHLEN + 100]; |
|
414 |
jint err; |
|
415 |
jdwpError serror; |
|
416 |
||
417 |
/* |
|
418 |
* If the transport is already loaded then use it |
|
419 |
* Note: We're assuming here that we don't support multiple |
|
420 |
* transports - when we do then we need to handle the case |
|
421 |
* where the transport library only supports a single environment. |
|
422 |
* That probably means we have a bag a transport environments |
|
423 |
* to correspond to the transports bag. |
|
424 |
*/ |
|
425 |
if (transport != NULL) { |
|
426 |
trans = transport; |
|
427 |
} else { |
|
428 |
serror = loadTransport(name, &trans); |
|
429 |
if (serror != JDWP_ERROR(NONE)) { |
|
430 |
return serror; |
|
431 |
} |
|
432 |
} |
|
433 |
||
434 |
if (isServer) { |
|
435 |
||
436 |
char *retAddress; |
|
437 |
char *launchCommand; |
|
438 |
TransportInfo *info; |
|
439 |
jvmtiError error; |
|
440 |
int len; |
|
441 |
char* prop_value; |
|
442 |
||
443 |
info = jvmtiAllocate(sizeof(*info)); |
|
444 |
if (info == NULL) { |
|
445 |
return JDWP_ERROR(OUT_OF_MEMORY); |
|
446 |
} |
|
447 |
info->name = jvmtiAllocate((int)strlen(name)+1); |
|
448 |
(void)strcpy(info->name, name); |
|
449 |
info->address = NULL; |
|
450 |
info->timeout = timeout; |
|
451 |
if (info->name == NULL) { |
|
452 |
serror = JDWP_ERROR(OUT_OF_MEMORY); |
|
453 |
goto handleError; |
|
454 |
} |
|
455 |
if (address != NULL) { |
|
456 |
info->address = jvmtiAllocate((int)strlen(address)+1); |
|
457 |
(void)strcpy(info->address, address); |
|
458 |
if (info->address == NULL) { |
|
459 |
serror = JDWP_ERROR(OUT_OF_MEMORY); |
|
460 |
goto handleError; |
|
461 |
} |
|
462 |
} |
|
463 |
||
464 |
info->transport = trans; |
|
465 |
||
466 |
err = (*trans)->StartListening(trans, address, &retAddress); |
|
467 |
if (err != JDWPTRANSPORT_ERROR_NONE) { |
|
468 |
printLastError(trans, err); |
|
469 |
serror = JDWP_ERROR(TRANSPORT_INIT); |
|
470 |
goto handleError; |
|
471 |
} |
|
472 |
||
473 |
/* |
|
474 |
* Record listener address in a system property |
|
475 |
*/ |
|
896
5c02031316bf
6725543: Compiler warnings in serviceability native code
ohair
parents:
2
diff
changeset
|
476 |
len = (int)strlen(name) + (int)strlen(retAddress) + 2; /* ':' and '\0' */ |
2 | 477 |
prop_value = (char*)jvmtiAllocate(len); |
478 |
strcpy(prop_value, name); |
|
479 |
strcat(prop_value, ":"); |
|
480 |
strcat(prop_value, retAddress); |
|
481 |
setTransportProperty(getEnv(), prop_value); |
|
482 |
jvmtiDeallocate(prop_value); |
|
483 |
||
484 |
||
485 |
(void)strcpy(threadName, "JDWP Transport Listener: "); |
|
486 |
(void)strcat(threadName, name); |
|
487 |
||
488 |
func = &acceptThread; |
|
489 |
error = spawnNewThread(func, (void*)info, threadName); |
|
490 |
if (error != JVMTI_ERROR_NONE) { |
|
491 |
serror = map2jdwpError(error); |
|
492 |
goto handleError; |
|
493 |
} |
|
494 |
||
495 |
launchCommand = debugInit_launchOnInit(); |
|
496 |
if (launchCommand != NULL) { |
|
497 |
serror = launch(launchCommand, name, retAddress); |
|
498 |
if (serror != JDWP_ERROR(NONE)) { |
|
499 |
goto handleError; |
|
500 |
} |
|
501 |
} else { |
|
502 |
if ( ! gdata->quiet ) { |
|
503 |
TTY_MESSAGE(("Listening for transport %s at address: %s", |
|
504 |
name, retAddress)); |
|
505 |
} |
|
506 |
} |
|
507 |
return JDWP_ERROR(NONE); |
|
508 |
||
509 |
handleError: |
|
510 |
jvmtiDeallocate(info->name); |
|
511 |
jvmtiDeallocate(info->address); |
|
512 |
jvmtiDeallocate(info); |
|
513 |
} else { |
|
514 |
/* |
|
515 |
* Note that we don't attempt to do a launch here. Launching |
|
516 |
* is currently supported only in server mode. |
|
517 |
*/ |
|
518 |
||
519 |
/* |
|
520 |
* If we're connecting to another process, there shouldn't be |
|
521 |
* any concurrent listens, so its ok if we block here in this |
|
522 |
* thread, waiting for the attach to finish. |
|
523 |
*/ |
|
524 |
err = (*trans)->Attach(trans, address, timeout, 0); |
|
525 |
if (err != JDWPTRANSPORT_ERROR_NONE) { |
|
526 |
printLastError(trans, err); |
|
527 |
serror = JDWP_ERROR(TRANSPORT_INIT); |
|
528 |
return serror; |
|
529 |
} |
|
530 |
||
531 |
/* |
|
532 |
* Start the transport loop in a separate thread |
|
533 |
*/ |
|
534 |
(void)strcpy(threadName, "JDWP Transport Listener: "); |
|
535 |
(void)strcat(threadName, name); |
|
536 |
||
537 |
func = &attachThread; |
|
538 |
err = spawnNewThread(func, (void*)trans, threadName); |
|
539 |
serror = map2jdwpError(err); |
|
540 |
} |
|
541 |
return serror; |
|
542 |
} |
|
543 |
||
544 |
void |
|
545 |
transport_close(void) |
|
546 |
{ |
|
547 |
if ( transport != NULL ) { |
|
548 |
(*transport)->Close(transport); |
|
549 |
} |
|
550 |
} |
|
551 |
||
552 |
jboolean |
|
553 |
transport_is_open(void) |
|
554 |
{ |
|
555 |
jboolean is_open = JNI_FALSE; |
|
556 |
||
557 |
if ( transport != NULL ) { |
|
558 |
is_open = (*transport)->IsOpen(transport); |
|
559 |
} |
|
560 |
return is_open; |
|
561 |
} |
|
562 |
||
563 |
jint |
|
564 |
transport_sendPacket(jdwpPacket *packet) |
|
565 |
{ |
|
566 |
jdwpTransportError err = JDWPTRANSPORT_ERROR_NONE; |
|
567 |
jint rc = 0; |
|
568 |
||
569 |
if (transport != NULL) { |
|
570 |
if ( (*transport)->IsOpen(transport) ) { |
|
571 |
debugMonitorEnter(sendLock); |
|
572 |
err = (*transport)->WritePacket(transport, packet); |
|
573 |
debugMonitorExit(sendLock); |
|
574 |
} |
|
575 |
if (err != JDWPTRANSPORT_ERROR_NONE) { |
|
576 |
if ((*transport)->IsOpen(transport)) { |
|
577 |
printLastError(transport, err); |
|
578 |
} |
|
579 |
||
580 |
/* |
|
581 |
* The users of transport_sendPacket except 0 for |
|
582 |
* success; non-0 otherwise. |
|
583 |
*/ |
|
584 |
rc = (jint)-1; |
|
585 |
} |
|
586 |
||
587 |
} /* else, bit bucket */ |
|
588 |
||
589 |
return rc; |
|
590 |
} |
|
591 |
||
592 |
jint |
|
593 |
transport_receivePacket(jdwpPacket *packet) |
|
594 |
{ |
|
595 |
jdwpTransportError err; |
|
596 |
||
597 |
err = (*transport)->ReadPacket(transport, packet); |
|
598 |
if (err != JDWPTRANSPORT_ERROR_NONE) { |
|
599 |
/* |
|
600 |
* If transport has been closed return EOF |
|
601 |
*/ |
|
602 |
if (!(*transport)->IsOpen(transport)) { |
|
603 |
packet->type.cmd.len = 0; |
|
604 |
return 0; |
|
605 |
} |
|
606 |
||
607 |
printLastError(transport, err); |
|
608 |
||
609 |
/* |
|
610 |
* Users of transport_receivePacket expect 0 for success, |
|
611 |
* non-0 otherwise. |
|
612 |
*/ |
|
613 |
return (jint)-1; |
|
614 |
} |
|
615 |
return 0; |
|
616 |
} |