1 #!/bin/sh 2 3 # 4 # Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. 5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 # 7 # This code is free software; you can redistribute it and/or modify it 8 # under the terms of the GNU General Public License version 2 only, as 9 # published by the Free Software Foundation. 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 26 # 27 # 28 # jtreg runs this in a scratch dir. 29 # It (and runregress -no) sets these env vars: 30 # TESTSRC: The dir that contains this file 31 # TESTCLASSES: Where .class files are compiled to 32 # TESTJAVA: The jdk to run 33 # 34 # This is a 'library' script that is included by 35 # shell script test cases that want to run a .java file as the debuggee 36 # and use jdb as the debugger. This file contains 37 # several functions that support such a test. 38 39 # The caller script can also set these shell vars before 40 # including this file: 41 # pkg=<package name> To use a package, define it here and put 42 # package $pkg 43 # in your java file 44 # classname=<classnam> Omit this to use the default class name, 'shtest'. 45 46 # compileOptions=<string> compile options for at least the first compile, 47 # eg, compileOptions=-g 48 # compileOptions2=<string> Options for the 2nd, ..., compile. compileOptions1 49 # is used if this is not set. To use no compile 50 # options for the 2nd ... compiles, do 51 # compileOptions2=none 52 # 53 # mode=-Xcomp or mode=-Xint to run in these modes. These should not 54 # really be used since the tests are normally 55 # run in both modes. 56 # javacCmd=path-to-javac to use a non-standard javac for compiling 57 # compileOptions=<string> Options to pass to javac 58 # 59 # See RedefineException.sh as an example of a caller script. 60 # 61 # To do RedefineClasses operations, embed @1 tags in the .java 62 # file to tell this script how to modify it to produce the 2nd 63 # version of the .class file to be used in the redefine operation. 64 # Here are examples of each editting tag and what change 65 # it causes in the new file. Note that blanks are not preserved 66 # in these editing operations. 67 # 68 # @1 uncomment 69 # orig: // @1 uncomment gus = 89; 70 # new: gus = 89; 71 # 72 # @1 commentout 73 # orig: gus = 89 // @1 commentout 74 # new: // gus = 89 // @1 commentout 75 # 76 # @1 delete 77 # orig: gus = 89 // @1 delete 78 # new: entire line deleted 79 # 80 # @1 newline 81 # orig: gus = 89; // @1 newline gus++; 82 # new: gus = 89; // 83 # gus++; 84 # 85 # @1 replace 86 # orig: gus = 89; // @1 replace gus = 90; 87 # new: gus = 90; 88 # 89 # The only other tag supported is @1 breakpoint. The setbkpts function 90 # sets bkpts at all lines that contain this string. 91 # 92 # Currently, all these tags are start with @1. It is envisioned that this script 93 # could be ehanced to allow multiple cycles of redefines by allowing 94 # @2, @3, ... tags. IE, processing the @i tags in the ith version of 95 # the file will produce the i+1th version of the file. 96 # 97 # There are problem with jtreg leaving behind orphan java and jdb processes 98 # when this script is run. Sometimes, on some platforms, it just doesn't 99 # get them all killed properly. 100 # The solution is to put a magic word in the cmd lines of background java 101 # and jdb processes this script launches. We can then do the right kind 102 # of ps cmds to find all these processes and kill them. We do this by 103 # trapping the completion of this script. 104 # 105 # An associated problem is that our trap handler (cleanup) doesn't 106 # always get called when jtreg terminates a test. This can leave tests 107 # hanging but following tests should run ok because each test uses 108 # unique names for the port and temp files (based on the PID returned 109 # by $$). 110 # 111 # mks 6.2a on win 98 presents two problems: 112 # $! returns the PID as a negative number whereas ps returns 113 # it in the form 0xFFF.... This means our trick of 114 # of using $! to get the PIDs of the jdb and debuggee processes 115 # doesn't work. This will cause some error cases to fail 116 # with a jtreg timeout instead of failing more gracefully. 117 # 118 # There is no form of the ps command that will show the whole 119 # cmd line. Thus, the magic keyword trick doesn't work. We 120 # resort to just killing java.exe and jdb.exes 121 # 122 # pid usage: 123 # debuggeepid: used in jdb process to detect if debuggee has died. 124 # - waitForDebuggeeMsg: fail if debuggee is gone 125 # 126 # jdbpid: dofail: used to detect if in main process or jdb process 127 # waitforfinish: quit if the jdb process is gone 128 129 #killcmd=/bin/kill 130 killcmd=kill 131 132 # This can be increased if timing seems to be an issue. 133 sleep_seconds=1 134 timeout_factor=1 135 if [ -n "$TESTTIMEOUTFACTOR" ] ; then 136 # convert float value to int 137 timeout_factor=$(echo $TESTTIMEOUTFACTOR | awk '{printf "%d\n", int($1)}') 138 fi 139 140 echo "ShellScaffold.sh: Running with timeout_factor = $timeout_factor" >& 2 141 topPid=$$ 142 143 # Be careful to echo to >& in these general functions. 144 # If they are called from the functions that are sending 145 # cmds to jdb, then stdout is redirected to jdb. 146 cleanup() 147 { 148 if [ -r "$failFile" ] ; then 149 ls -l "$failFile" >&2 150 echo "<cleanup:_begin_failFile_contents>" >&2 151 cat "$failFile" >&2 152 echo "<cleanup:_end_failFile_contents>" >&2 153 fi 154 155 # Kill all processes that have our special 156 # keyword in their cmd line. 157 killOrphans cleanup $jdbKeyword 158 killOrphans cleanup $debuggeeKeyword 159 } 160 161 # Kill all processes with $2 in their cmd lines 162 # Print a msg about this using $1 as the prefix 163 killOrphans() 164 { 165 str=$2 166 167 if [ -z "$isCygwin" ] ; then 168 toBeKilled=`$psCmd | $grep -v grep | $grep -i $str | awk '{print $1}' | tr '\n\r' ' '` 169 else 170 # The cygwin ps command doesn't show the options passed to a cmd. 171 # We will use jps to get the win PID of the command, and 172 # then use ps to find the cygwin pid to be killed. 173 # The form of a ps output line is 174 # ^ ddddd dddd dddd dddd.* 175 # where the 4th digits are the win pid and the first 176 # are the cygwin pid. 177 if [ -r "$jdk/bin/$jstack" ] ; then 178 winPid=`$jdk/bin/jps -v | $grep -i $str | sed -e 's@ .*@@'` 179 if [ ! -z "$winPid" ] ; then 180 # Here is a way to kill using a win cmd and the win PID. 181 #echo "$1: taskkill /F $winPid" >& 2 182 #taskkill /F /PID $winPid 183 184 toBeKilled=`$psCmd | $grep -v grep | \ 185 $grep '^ +[0-9]+ +[0-9]+ +[0-9]+ +'"$winPid" |\ 186 awk '{print $1}' | tr '\n\r' ' '` 187 fi 188 else 189 # Well, too bad - we can't find what to kill. 190 toBeKilled= 191 fi 192 fi 193 194 if [ ! -z "$toBeKilled" ] ; then 195 echo "$1: kill -9 $toBeKilled" >& 2 196 kill -9 $toBeKilled 197 fi 198 } 199 200 # Returns 0 if $1 is the pid of a running process 201 findPid() 202 { 203 if [ -z "$1" ] ; then 204 return 1 205 fi 206 207 case "$osname" in 208 SunOS | AIX) 209 $psCmd | $grep '^ *'"$1 " > $devnull 2>&1 210 res=$? 211 ;; 212 Windows* | CYGWIN*) 213 # Don't use ps on cygwin since it sometimes misses 214 # some processes (!). 215 tasklist /NH | $grep " $1 " > $devnull 2>&1 216 res=$? 217 ;; 218 *) 219 # Never use plain 'ps', which requires a "controlling terminal" 220 # and will fail with a "ps: no controlling terminal" error. 221 # Running under 'rsh' will cause this ps error. 222 $psCmd -e | $grep '^ *'"$1 " > $devnull 2>&1 223 res=$? 224 ;; 225 esac 226 return $res 227 } 228 229 setup() 230 { 231 failed= 232 # This is used to tag each java and jdb cmd we issue so 233 # we can kill them at the end of the run. 234 235 orphanKeyword=HANGINGJAVA-$$ 236 debuggeeKeyword=${orphanKeyword}_DEB 237 jdbKeyword=${orphanKeyword}_JDB 238 baseArgs=-D${debuggeeKeyword} 239 if [ -z "$TESTCLASSES" ] ; then 240 echo "--Warning: TESTCLASSES is not defined; using TESTCLASSES=." 241 echo " You should run: " 242 echo " runregress $0 -no" 243 echo " or" 244 echo " (setenv TESTCLASSES .; $0 $*)" 245 TESTCLASSES=. 246 fi 247 if [ ! -z "$TESTJAVA" ] ; then 248 jdk="$TESTJAVA" 249 else 250 echo "--Error: TESTJAVA must be defined as the pathname of a jdk to test." 251 exit 1 252 fi 253 254 ulimitCmd= 255 osname=`uname -s` 256 isCygwin= 257 case "$osname" in 258 Windows* | CYGWIN*) 259 devnull=NUL 260 case "$osname" in 261 CYGWIN*) 262 isCygwin=1 263 devnull=/dev/null 264 ;; 265 esac 266 267 if [ -r $jdk/bin/dt_shmem.dll ] ; then 268 transport=dt_shmem 269 address=kkkk.$$ 270 else 271 transport=dt_socket 272 address= 273 fi 274 baseArgs="$baseArgs -XX:-ShowMessageBoxOnError" 275 # jtreg puts \\s in TESTCLASSES and some uses, eg. echo 276 # treat them as control chars on mks (eg \t is tab) 277 # Oops; windows mks really seems to want this cat line 278 # to start in column 1 279 if [ -w "$Temp" ] ; then 280 tmpFile=$Temp/tmp.$$ 281 elif [ -w "$TEMP" ] ; then 282 tmpFile=$TEMP/tmp.$$ 283 else 284 tmpFile=tmp.$$ 285 fi 286 cat <<EOF >$tmpFile 287 $TESTCLASSES 288 EOF 289 TESTCLASSES=`cat $tmpFile | sed -e 's@\\\\@/@g'` 290 rm -f $tmpFile 291 # on mks 292 grep=egrep 293 psCmd=ps 294 jstack=jstack.exe 295 ;; 296 SunOS | Linux | Darwin | AIX) 297 transport=dt_socket 298 address= 299 devnull=/dev/null 300 grep=egrep 301 jstack=jstack 302 # On linux, core files take a long time, and can leave 303 # zombie processes 304 if [ "$osname" = SunOS ] ; then 305 # Experiments show Solaris '/usr/ucb/ps -axwww' and 306 # '/usr/bin/pgrep -f -l' provide the same small amount of the 307 # argv string (PRARGSZ=80 in /usr/include/sys/procfs.h) 308 # 1) This seems to have been working OK in ShellScaffold. 309 # 2) OpenSolaris does not provide /usr/ucb/ps, so use pgrep 310 # instead 311 # The alternative would be to use /usr/bin/pargs [pid] to get 312 # all the args for a process, splice them back into one 313 # long string, then grep. 314 UU=`/usr/xpg4/bin/id -u -n` 315 psCmd="pgrep -f -l -U $UU" 316 else 317 ulimit -c 0 318 # See bug 6238593. 319 psCmd="ps axwww" 320 fi 321 ;; 322 *) 323 echo "--Error: Unknown result from 'uname -s': $osname" 324 exit 1 325 ;; 326 esac 327 328 329 tmpFileDir=$TESTCLASSES/aa$$ 330 TESTCLASSES=$tmpFileDir 331 332 mkdir -p $tmpFileDir 333 334 # This must not contain 'jdb' or it shows up 335 # in grep of ps output for some platforms 336 jdbOutFile=$tmpFileDir/jxdbOutput.txt 337 rm -f $jdbOutFile 338 touch $jdbOutFile 339 340 debuggeeOutFile=$tmpFileDir/debuggeeOutput.txt 341 failFile=$tmpFileDir/testFailed 342 debuggeepidFile=$tmpFileDir/debuggeepid 343 rm -f $failFile $debuggeepidFile 344 if [ -f "$failFile" ]; then 345 echo "ERROR: unable to delete existing failFile:" >&2 346 ls -l "$failFile" >&2 347 fi 348 349 if [ -z "$pkg" ] ; then 350 pkgSlash= 351 pkgDot= 352 redefineSubdir=. 353 else 354 pkgSlash=$pkg/ 355 pkgDot=$pkg. 356 redefineSubdir=$pkgSlash 357 fi 358 if [ -z "$classname" ] ; then 359 classname=shtest 360 fi 361 362 if [ -z "$java" ] ; then 363 java=java 364 fi 365 366 if [ -z "$jdb" ] ; then 367 jdb=$jdk/bin/jdb 368 fi 369 370 ####################################################3 371 ####################################################3 372 ####################################################3 373 ####################################################3 374 # sol: this gets all processes killed but 375 # no jstack 376 # linux same as above 377 # win mks: No dice; processes still running 378 trap "cleanup" 0 1 2 3 4 6 9 10 15 379 380 jdbOptions="$jdbOptions -J-D${jdbKeyword}" 381 } 382 383 docompile() 384 { 385 if [ "$compile" = 0 ] ; then 386 return 387 fi 388 saveDir=`pwd` 389 cd $tmpFileDir 390 rm -f *.java 391 createJavaFile $classname 392 393 # Compile two versions of the file, the original and with the 394 # indicated lines modified. 395 cp $classname.java.1 $classname.java 396 echo "--Compiling first version of `pwd`/$classname.java with options: $compileOptions" 397 # Result is in $pkgSlash$classname.class 398 399 if [ -z "$javacCmd" ] ; then 400 javacCmd=$jdk/bin/javac 401 fi 402 403 echo "compiling " `ls *.java` 404 $javacCmd $compileOptions -d . *.java 405 if [ $? != 0 ] ; then 406 dofail "First compile failed" 407 fi 408 if [ -r vers1 ] ; then 409 rm -rf vers1 410 fi 411 mkdir -p vers1 412 mv *.class vers1 413 if [ ! -z "$compileOptions2" ] ; then 414 if [ "$compileOptions2" = none ] ; then 415 compileOptions= 416 else 417 compileOptions=$compileOptions2 418 fi 419 fi 420 421 while [ 1 = 1 ] ; do 422 # Not really a loop; just a way to avoid goto 423 # by using breaks 424 sed -e '/@1 *delete/ d' \ 425 -e 's! *// *@1 *uncomment! !' \ 426 -e 's!\(.*@1 *commentout\)!//\1!' \ 427 -e 's/@1 *newline/\ 428 /' \ 429 -e 's/.*@1 *replace//' \ 430 $classname.java.1 >$classname.java 431 432 cmp -s $classname.java.1 $classname.java 433 if [ $? = 0 ] ; then 434 break 435 fi 436 echo 437 echo "--Compiling second version of `pwd`/$classname.java with $compileOptions" 438 $javacCmd $compileOptions -d . $classname.java 439 if [ $? != 0 ] ; then 440 dofail "Second compile failed" 441 fi 442 if [ -r vers2 ] ; then 443 rm -rf vers2 444 fi 445 mkdir -p vers2 446 mv *.class vers2 447 mv $classname.java $classname.java.2 448 cp $classname.java.1 $classname.java 449 450 ###### Do the same for @2, and @3 allowing 3 redefines to occur. 451 ###### If I had more time to write sed cmds, I would do 452 ###### this in a loop. But, I don't think we will ever need 453 ###### more than 3 redefines. 454 sed -e '/@2 *delete/ d' \ 455 -e 's! *// *@2 *uncomment! !' \ 456 -e 's!\(.*@2 *commentout\)!//\1!' \ 457 -e 's/@2 *newline/\ 458 /' \ 459 -e 's/.*@2 *replace//' \ 460 $classname.java.2 >$classname.java 461 cmp -s $classname.java.2 $classname.java 462 if [ $? = 0 ] ; then 463 break 464 fi 465 echo 466 echo "--Compiling third version of `pwd`/$classname.java with $compileOptions" 467 $javacCmd $compileOptions -d . $classname.java 468 if [ $? != 0 ] ; then 469 dofail "Third compile failed" 470 fi 471 if [ -r vers3 ] ; then 472 rm -rf vers3 473 fi 474 mkdir -p vers3 475 mv *.class vers3 476 mv $classname.java $classname.java.3 477 cp $classname.java.1 $classname.java 478 479 ######## 480 sed -e '/@3 *delete/ d' \ 481 -e 's! *// *@3 *uncomment! !' \ 482 -e 's!\(.*@3 *commentout\)!//\1!' \ 483 -e 's/@3 *newline/\ 484 /' \ 485 -e 's/.*@3 *replace//' \ 486 $classname.java.3 >$classname.java 487 cmp -s $classname.java.3 $classname.java 488 if [ $? = 0 ] ; then 489 break 490 fi 491 echo 492 echo "--Compiling fourth version of `pwd`/$classname.java with $compileOptions" 493 $javacCmd $compileOptions -d . $classname.java 494 if [ $? != 0 ] ; then 495 dofail "fourth compile failed" 496 fi 497 if [ -r vers4 ] ; then 498 rm -rf vers4 499 fi 500 mkdir -p vers4 501 mv *.class vers4 502 mv $classname.java $classname.java.4 503 cp $classname.java.1 $classname.java 504 break 505 fgrep @4 $classname.java 506 if [ $? = 0 ] ; then 507 echo "--Error: @4 and above are not yet allowed" 508 exit 1 509 fi 510 done 511 512 cp vers1/* $redefineSubdir 513 cd $saveDir 514 } 515 516 # Send a cmd to jdb and wait for the jdb prompt to appear. 517 # We don't want to allow > as a prompt because if the debuggee 518 # runs for awhile after a command, jdb will show this prompt 519 # but is not really ready to accept another command for the 520 # debuggee - ie, a cont in this state will be ignored. 521 # If it ever becomes necessary to send a jdb command before 522 # a main[10] form of prompt appears, then this 523 # code will have to be modified. 524 # 525 # Specify $1 = allowExit to show that the command given 526 # allows JDB to exit 527 cmd() 528 { 529 allowExit= 530 case "$1" in 531 allowExit) 532 allowExit="allowExit" 533 shift 534 ;; 535 exitJdb) 536 # Quit JDB only with this cmd() invocation 537 echo "--Sending cmd: quit" >& 2 538 echo quit 539 echo "--Quit cmd was sent" >& 2 540 # See 6562090. Maybe there is a way that the exit 541 # can cause jdb to not get the quit. 542 sleep 5 543 544 # The exit code value here doesn't matter since this function 545 # is called as part of a pipeline and it is not the last command 546 # in the pipeline. 547 exit 1 548 ;; 549 esac 550 command=$* 551 552 if [ -z "$command" ] ; then 553 dofail "Command can't be a null string. Test failure" 554 fi 555 if [ "$command" = "quit" -o "$command" = "exit" ] ; then 556 # We don't want the test to manually quit jdb, 557 # we will do it in the end automatically 558 dofail "It's not allowed to send quit or exit commands from the test" 559 fi 560 if [ -r "$failFile" ] ; then 561 # failFile exists, it's better to finish execution 562 dofinish "quit" 563 fi 564 565 # $jdbOutFile always exists here and is non empty 566 # because after starting jdb, we waited 567 # for the prompt. 568 fileSize=`wc -c $jdbOutFile | awk '{ print $1 }'` 569 echo "--Sending cmd: " $command >&2 570 571 # jjh: We have a few intermittent failures here. 572 # It is as if every so often, jdb doesn't 573 # get the first cmd that is sent to it here. 574 # (actually, I have seen it get the first cmd ok, 575 # but then not get some subsequent cmd). 576 # It seems like jdb really doesn't get the cmd; jdb's response 577 # does not appear in the jxdboutput file. It contains: 578 # main[1] 579 # The application has been disconnected 580 581 # Is it possible 582 # that jdb got the cmd ok, but its response didn't make 583 # it to the jxdboutput file? If so, why did 'The application 584 # has been disconnected' make it? 585 586 # This causes the following loop to timeout and the test to fail. 587 # The above echo works because the cmd (stop at ...) 588 # is in the System.err shown in the .jtr file. 589 # Also, the cmd is shown in the 'jdb never responded ...' 590 # msg output below after the timeout. 591 # And, we know jdb is started because the main[1] output is in the .jtr 592 # file. And, we wouldn't have gotten here if mydojdbcmds hadn't 593 # seen the ]. 594 echo $command 595 596 # Now we have to wait for the next jdb prompt. We wait for a pattern 597 # to appear in the last line of jdb output. Normally, the prompt is 598 # 599 # 1) ^main[89] @ 600 # 601 # where ^ means start of line, and @ means end of file with no end of line 602 # and 89 is the current command counter. But we have complications e.g., 603 # the following jdb output can appear: 604 # 605 # 2) a[89] = 10 606 # 607 # The above form is an array assignment and not a prompt. 608 # 609 # 3) ^main[89] main[89] ... 610 # 611 # This occurs if the next cmd is one that causes no jdb output, e.g., 612 # 'trace methods'. 613 # 614 # 4) ^main[89] [main[89]] .... > @ 615 # 616 # jdb prints a > as a prompt after something like a cont. 617 # Thus, even though the above is the last 'line' in the file, it 618 # isn't the next prompt we are waiting for after the cont completes. 619 # HOWEVER, sometimes we see this for a cont command: 620 # 621 # ^main[89] $ 622 # <lines output for hitting a bkpt> 623 # 624 # 5) ^main[89] > @ 625 # 626 # i.e., the > prompt comes out AFTER the prompt we we need to wait for. 627 # 628 # So, how do we know when the next prompt has appeared?? 629 # 1. Search for 630 # main[89] $ 631 # This will handle cases 1, 2, 3 632 # 2. This leaves cases 4 and 5. 633 # 634 # What if we wait for 4 more chars to appear and then search for 635 # 636 # main[89] [>]$ 637 # 638 # on the last line? 639 # 640 # a. if we are currently at 641 # 642 # ^main[89] main[89] @ 643 # 644 # and a 'trace methods comes in, we will wait until at least 645 # 646 # ^main[89] main[89] main@ 647 # 648 # and then the search will find the new prompt when it completes. 649 # 650 # b. if we are currently at 651 # 652 # ^main[89] main[89] @ 653 # 654 # and the first form of cont comes in, then we will see 655 # 656 # ^main[89] main[89] > $ 657 # ^x@ 658 # 659 # where x is the first char of the msg output when the bkpt is hit 660 # and we will start our search, which will find the prompt 661 # when it comes out after the bkpt output, with or without the 662 # trailing > 663 # 664 665 # wait for 4 new chars to appear in the jdb output 666 count=0 667 desiredFileSize=`expr $fileSize + 4` 668 msg1=`echo At start: cmd/size/waiting : $command / $fileSize / \`date\`` 669 timeLimit=`expr 60 * $timeout_factor` 670 while [ 1 = 1 ] ; do 671 newFileSize=`wc -c $jdbOutFile | awk '{ print $1 } '` 672 #echo jj: desired = $desiredFileSize, new = $newFileSize >& 2 673 674 done=`expr $newFileSize \>= $desiredFileSize` 675 if [ $done = 1 ] ; then 676 break 677 fi 678 sleep ${sleep_seconds} 679 count=`expr $count + ${sleep_seconds}` 680 if [ $count -gt $timeLimit ] ; then 681 # record some debug info. 682 echo "--DEBUG: jdb $$ didn't respond to command in $count secs: $command" >& 2 683 echo "--DEBUG:" $msg1 >& 2 684 echo "--DEBUG: "done size/waiting : / $newFileSize / `date` >& 2 685 echo "-- $jdbOutFile follows-------------------------------" >& 2 686 cat $jdbOutFile >& 2 687 echo "------------------------------------------" >& 2 688 dojstack 689 dofail "jdb never responded to command: $command" 690 fi 691 done 692 # Note that this assumes just these chars in thread names. 693 waitForJdbMsg '[a-zA-Z0-9_-][a-zA-Z0-9_-]*\[[1-9][0-9]*\] [ >]*$' 1 $allowExit 694 } 695 696 setBkpts() 697 { 698 # Can set multiple bkpts, but only in one class. 699 # $1 is the bkpt name, eg, @1 700 allLines=`$grep -n "$1 *breakpoint" $tmpFileDir/$classname.java.1 | sed -e 's@^\([0-9]*\).*@\1@g'` 701 for ii in $allLines ; do 702 cmd "stop at $pkgDot$classname:$ii" 703 done 704 } 705 706 runToBkpt() 707 { 708 # Don't pass allowExit here as we don't want JDB to unexpectedly exit 709 cmd run 710 # Don't need to do this - the above waits for the next prompt which comes out 711 # AFTER the Breakpoint hit message. 712 # Wait for jdb to hit the bkpt 713 #waitForJdbMsg "Breakpoint hit" 5 714 } 715 716 contToBkpt() 717 { 718 # Don't pass allowExit here as we don't want JDB to unexpectedly exit 719 cmd cont 720 # Don't need to do this - the above waits for the next prompt which comes out 721 # AFTER the Breakpoint hit message. 722 # Wait for jdb to hit the bkpt 723 #waitForJdbMsg "Breakpoint hit" 5 724 } 725 726 727 # Wait until string $1 appears in the output file, within the last $2 lines 728 # If $3 is allowExit, then don't fail if jdb exits before 729 # the desired string appears. 730 waitForJdbMsg() 731 { 732 # This can be called from the jdb thread which doesn't 733 # have access to $debuggeepid, so we have to read it from the file. 734 nlines=$2 735 allowExit="$3" 736 myCount=0 737 timeLimit=`expr 40 * $timeout_factor` # wait a max of this many secs for a response from a jdb command 738 739 while [ 1 = 1 ] ; do 740 if [ -r $jdbOutFile ] ; then 741 # Something here causes jdb to complain about Unrecognized cmd on x86. 742 tail -$nlines $jdbOutFile | $grep -s "$1" > $devnull 2>&1 743 if [ $? = 0 ] ; then 744 # Found desired string 745 break 746 fi 747 fi 748 tail -2 $jdbOutFile | $grep -s "The application exited" > $devnull 2>&1 749 if [ $? = 0 ] ; then 750 # Found 'The application exited' 751 echo "--JDB finished: The application exited" >&2 752 if [ ! -z "$allowExit" ] ; then 753 # Exit is allowed 754 dofinish 755 fi 756 # Otherwise, it is an error if we don't find $1 757 if [ -r $jdbOutFile ] ; then 758 tail -$nlines $jdbOutFile | $grep -s "$1" > $devnull 2>&1 759 if [ $? = 0 ] ; then 760 break 761 fi 762 fi 763 dofail "JDB unexpectedly finished: Waited for jdb msg $1, but it never appeared" 764 fi 765 766 sleep ${sleep_seconds} 767 findPid $topPid 768 if [ $? != 0 ] ; then 769 echo "--Top process ($topPid) is dead. We better die too" >&2 770 dojstack 771 exit 1 772 fi 773 774 myCount=`expr $myCount + ${sleep_seconds}` 775 if [ $myCount -gt $timeLimit ] ; then 776 echo "--Fail: waitForJdbMsg timed out after $timeLimit seconds, looking for /$1/, in $nlines lines; exiting" >> $failFile 777 echo "vv jdbOutFile vvvvvvvvvvvvvvvvvvvvvvvvvvvv" >& 2 778 cat $jdbOutFile >& 2 779 echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >& 2 780 dojstack 781 exit 1 782 fi 783 done 784 785 } 786 787 # Finishes JDB execution 788 # Specify command to finish if it's needed 789 dofinish() 790 { 791 if [ ! -z "$*" ] ; then 792 echo "--Finish execution with sending \"$*\" command to JDB" >&2 793 cmd "exitJdb" "$*" 794 else 795 echo "--Finish without sending \"quit\" command to JDB" >&2 796 fi 797 exit 0 798 } 799 800 # $1 is the string to print. If $2 exists, 801 # it is the name of a file to print, ie, the name 802 # of the file that contains the $1 string. 803 dofail() 804 { 805 if [ ! -z "$jdbpid" ] ; then 806 # we are in the main process instead of the jdb process 807 echo " " >> $failFile 808 echo "--Fail: main: $*" >> $failFile 809 else 810 # Kill the debuggee ; it could be hung so 811 # we want to get rid of it as soon as possible. 812 killOrphans "killing debuggee" $debuggeeKeyword 813 # Kill debugger, it could be hung 814 killOrphans "killing debugger" $jdbKeyword 815 816 echo " " >>$failFile 817 echo "--Fail: $*" >> $failFile 818 fi 819 if [ ! -z "$2" ] ; then 820 echo "---- contents of $2 follows -------" >> $failFile 821 cat "$2" >> $failFile 822 echo "---------------" >>$failFile 823 fi 824 exit 1 825 } 826 827 828 redefineClass() 829 { 830 if [ -z "$1" ] ; then 831 vers=2 832 else 833 vers=`echo $1 | sed -e 's/@//'` 834 vers=`expr $vers + 1` 835 fi 836 837 cmd "redefine $pkgDot$classname $tmpFileDir/vers$vers/$classname.class" 838 839 cp $tmpFileDir/$classname.java.$vers \ 840 $tmpFileDir/$classname.java 841 } 842 843 mydojdbCmds() 844 { 845 # Wait for jdb to start before we start sending cmds 846 waitForJdbMsg ']' 1 847 # Send commands from the test 848 dojdbCmds 849 # Finish jdb with quit command 850 dofinish "quit" 851 } 852 853 startJdb() 854 { 855 if [ ! -r "$jdb" -a ! -r "$jdb.exe" ] ; then 856 dofail "$jdb does not exist" 857 fi 858 echo 859 echo "--Starting jdb, address=$address" 860 if [ -z "$address" ] ; then 861 # Let jdb choose the port and write it to stdout 862 mydojdbCmds | $jdb $jdbOptions -listenany | tee $jdbOutFile & 863 864 while [ 1 ] ; do 865 lastLine=`$grep 'Listening at address' $jdbOutFile` 866 if [ ! -z "$lastLine" ] ; then 867 break 868 fi 869 sleep 1 870 done 871 # jjh: we got the address ok, and seemed to start the debuggee 872 address=`echo $lastLine | sed -e 's@.*: *@@'` 873 else 874 mydojdbCmds | $jdb $jdbOptions -listen $address | tee $jdbOutFile & 875 fi 876 #echo address = $address 877 878 879 # this gets the pid of tee, at least it does on solaris 880 jdbpid=$! 881 882 # This fails on linux because there is an entry for each thread in jdb 883 # so we get a list of numbers in jdbpid 884 # jdbpid=`$psCmd | $grep -v grep | $grep ${orphanKeyword}_JDB | awk '{print $1}' | tr '\n\r' ' '` 885 } 886 887 startDebuggee() 888 { 889 args="$TESTVMOPTS $TESTJAVAOPTS" 890 891 if [ ! -z "$args" ] ; then 892 echo "--Starting debuggee with args from TESTVMOPTS and/or TESTJAVAOPTS: $args" 893 else 894 echo "--Starting debuggee" 895 fi 896 897 debuggeepid= 898 waitForJdbMsg Listening 4 899 900 beOption="-agentlib:jdwp=transport=$transport,address=$address,server=n,suspend=y" 901 # beOption="-Xdebug -Xrunjdwp:transport=$transport,address=$address,server=n,suspend=y" 902 903 thecmd="$jdk/bin/$java $mode -classpath $tmpFileDir $baseArgs $args \ 904 -Djtreg.classDir=$TESTCLASSES \ 905 -showversion \ 906 $beOption \ 907 $pkgDot$classname" 908 echo "Cmd: $thecmd" 909 910 sh -c "$thecmd | tee $debuggeeOutFile" & 911 912 # Note that the java cmd and the tee cmd will be children of 913 # the sh process. We can use that to find them to kill them. 914 debuggeepid=$! 915 916 # Save this in a place where the jdb process can find it. 917 # Note that it is possible for the java cmd to abort during startup 918 # due to a bad classpath or whatever. 919 echo $debuggeepid > $debuggeepidFile 920 } 921 922 dojstack() 923 { 924 if [ -r "$jdk/bin/$jstack" ] ; then 925 # If jstack exists, so will jps 926 # Show stack traces of jdb and debuggee as a possible debugging aid. 927 jdbCmd=`$jdk/bin/jps -v | $grep $jdbKeyword` 928 realJdbPid=`echo "$jdbCmd" | sed -e 's@ .*@@'` 929 if [ ! -z "$realJdbPid" ] ; then 930 echo "-- jdb process info ----------------------" >&2 931 echo " $jdbCmd" >&2 932 echo "-- jdb threads: jstack $realJdbPid" >&2 933 $jdk/bin/$jstack $realJdbPid >&2 934 echo "------------------------------------------" >&2 935 echo >&2 936 fi 937 debuggeeCmd=`$jdk/bin/jps -v | $grep $debuggeeKeyword` 938 realDebuggeePid=`echo "$debuggeeCmd" | sed -e 's@ .*@@'` 939 if [ ! -z "$realDebuggeePid" ] ; then 940 echo "-- debuggee process info ----------------------" >&2 941 echo " $debuggeeCmd" >&2 942 echo "-- debuggee threads: jstack $moption $realDebuggeePid" >&2 943 $jdk/bin/$jstack $realDebuggeePid >&2 944 echo "=============================================" >&2 945 echo >&2 946 fi 947 fi 948 } 949 950 waitForFinish() 951 { 952 # This is the main process 953 # Wait for the jdb process to finish, or some error to occur 954 955 while [ 1 = 1 ] ; do 956 findPid $jdbpid 957 if [ $? != 0 ] ; then 958 break 959 fi 960 961 # (Don't use jdbFailIfPresent here since it is not safe 962 # to call from different processes) 963 $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 964 if [ $? = 0 ] ; then 965 dofail "jdb input stream closed prematurely" 966 fi 967 968 # If a failure has occured, quit 969 if [ -r "$failFile" ] ; then 970 break 971 fi 972 973 sleep ${sleep_seconds} 974 done 975 976 # jdb exited because its input stream closed prematurely 977 # (Don't use jdbFailIfPresent here since it is not safe 978 # to call from different processes) 979 $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 980 if [ $? = 0 ] ; then 981 dofail "jdb input stream closed prematurely" 982 fi 983 984 # It is necessary here to avoid the situation when JDB exited but 985 # mydojdbCmds() didn't finish because it waits for JDB message 986 # in waitForJdbMsg(), at the same time main process will finish 987 # the execution with no errors. 988 # To avoid that, wait for spawned processes to finish 989 case "$osname" in 990 SunOS) 991 # `wait` function doesn't work in Solaris shell as in bash, 992 # so create replacement that finds mydojdbCmds() shell process 993 # and waits for its finish 994 cmdsPid= 995 # get list of processes except main process with $topPid 996 processes=`$psCmd | $grep -v "$grep" | $grep -v $topPid | awk '{print $1}'` 997 for pid in $processes; do 998 # for each process grep its full args string for test name $0 999 # $0 contains full test name with path 1000 pargs -l $pid 2>$devnull | $grep "$0" >$devnull 2>&1 1001 if [ $? = 0 ] ; then 1002 cmdsPid=$pid 1003 break 1004 fi 1005 done 1006 echo "--waitForFinish: Waiting for mydojdbCmds() to finish" >&2 1007 while [ 1 = 1 ] ; do 1008 findPid $cmdsPid 1009 if [ $? != 0 ] ; then 1010 break 1011 fi 1012 sleep ${sleep_seconds} 1013 done 1014 ;; 1015 *) 1016 echo "--waitForFinish: Waiting for all processes to finish" >&2 1017 wait 1018 ;; 1019 esac 1020 1021 if [ -r "$failFile" ] ; then 1022 ls -l "$failFile" >&2 1023 echo "<waitForFinish:_begin_failFile_contents>" >&2 1024 cat "$failFile" >&2 1025 echo "<waitForFinish:_end_failFile_contents>" >&2 1026 exit 1 1027 fi 1028 } 1029 1030 # $1 is the filename, $2 is the string to look for, 1031 # $3 is the number of lines to search (from the end) 1032 grepForString() 1033 { 1034 if [ -z "$3" ] ; then 1035 theCmd=cat 1036 else 1037 theCmd="tail -$3" 1038 fi 1039 1040 case "$2" in 1041 *\>*) 1042 # Target string contains a '>' so we better not ignore it 1043 $theCmd $1 | $grep -s "$2" > $devnull 2>&1 1044 stat="$?" 1045 ;; 1046 *) 1047 # Target string does not contain a '>'. 1048 # NOTE: if $1 does not end with a new line, piping it to sed 1049 # doesn't include the chars on the last line. Detect this 1050 # case, and add a new line. 1051 theFile="$1" 1052 if [ `tail -1 "$theFile" | wc -l | sed -e 's@ @@g'` = 0 ] ; then 1053 # The target file doesn't end with a new line so we have 1054 # add one to a copy of the target file so the sed command 1055 # below can filter that last line. 1056 cp "$theFile" "$theFile.tmp" 1057 theFile="$theFile.tmp" 1058 echo >> "$theFile" 1059 fi 1060 1061 # See bug 6220903. Sometimes the jdb prompt chars ('> ') can 1062 # get interleaved in the target file which can keep us from 1063 # matching the target string. 1064 $theCmd "$theFile" | sed -e 's@> @@g' -e 's@>@@g' \ 1065 | $grep -s "$2" > $devnull 2>&1 1066 stat=$? 1067 if [ "$theFile" != "$1" ]; then 1068 # remove the copy of the target file 1069 rm -f "$theFile" 1070 fi 1071 unset theFile 1072 esac 1073 1074 return $stat 1075 } 1076 1077 # $1 is the filename, $2 is the regexp to match and return, 1078 # $3 is the number of lines to search (from the end) 1079 matchRegexp() 1080 { 1081 if [ -z "$3" ] ; then 1082 theCmd=cat 1083 else 1084 theCmd="tail -$3" 1085 fi 1086 1087 case "$2" in 1088 *\>*) 1089 # Target string contains a '>' so we better not ignore it 1090 res=`$theCmd $1 | sed -e "$2"` 1091 ;; 1092 *) 1093 # Target string does not contain a '>'. 1094 # NOTE: if $1 does not end with a new line, piping it to sed 1095 # doesn't include the chars on the last line. Detect this 1096 # case, and add a new line. 1097 theFile="$1" 1098 if [ `tail -1 "$theFile" | wc -l | sed -e 's@ @@g'` = 0 ] ; then 1099 # The target file doesn't end with a new line so we have 1100 # add one to a copy of the target file so the sed command 1101 # below can filter that last line. 1102 cp "$theFile" "$theFile.tmp" 1103 theFile="$theFile.tmp" 1104 echo >> "$theFile" 1105 fi 1106 1107 # See bug 6220903. Sometimes the jdb prompt chars ('> ') can 1108 # get interleaved in the target file which can keep us from 1109 # matching the target string. 1110 res=`$theCmd "$theFile" | sed -e 's@> @@g' -e 's@>@@g' \ 1111 | sed -e "$2"` 1112 if [ "$theFile" != "$1" ]; then 1113 # remove the copy of the target file 1114 rm -f "$theFile" 1115 fi 1116 unset theFile 1117 esac 1118 return $res 1119 } 1120 1121 # $1 is the filename, $2 is the string to look for, 1122 # $3 is the number of lines to search (from the end) 1123 failIfPresent() 1124 { 1125 if [ -r "$1" ] ; then 1126 grepForString "$1" "$2" "$3" 1127 if [ $? = 0 ] ; then 1128 dofail "Error output found: \"$2\" in $1" $1 1129 fi 1130 fi 1131 } 1132 1133 # $1 is the filename, $2 is the string to look for 1134 # $3 is the number of lines to search (from the end) 1135 failIfNotPresent() 1136 { 1137 if [ ! -r "$1" ] ; then 1138 dofail "Required output \"$2\" not found in $1" 1139 fi 1140 grepForString "$1" "$2" "$3" 1141 if [ $? != 0 ] ; then 1142 dofail "Required output \"$2\" not found in $1" $1 1143 fi 1144 1145 } 1146 1147 # fail if $1 is not in the jdb output 1148 # $2 is the number of lines to search (from the end) 1149 jdbFailIfNotPresent() 1150 { 1151 failIfNotPresent $jdbOutFile "$1" $2 1152 } 1153 1154 # fail if $1 is not in the debuggee output 1155 # $2 is the number of lines to search (from the end) 1156 debuggeeFailIfNotPresent() 1157 { 1158 failIfNotPresent $debuggeeOutFile "$1" $2 1159 } 1160 1161 # fail if $1 is in the jdb output 1162 # $2 is the number of lines to search (from the end) 1163 jdbFailIfPresent() 1164 { 1165 failIfPresent $jdbOutFile "$1" $2 1166 } 1167 1168 # fail if $1 is in the debuggee output 1169 # $2 is the number of lines to search (from the end) 1170 debuggeeFailIfPresent() 1171 { 1172 failIfPresent $debuggeeOutFile "$1" $2 1173 } 1174 1175 # match and return the output from the regexp $1 in the debuggee output 1176 # $2 is the number of lines to search (from the end) 1177 debuggeeMatchRegexp() 1178 { 1179 matchRegexp $debuggeeOutFile "$1" $2 1180 } 1181 1182 1183 # This should really be named 'done' instead of pass. 1184 pass() 1185 { 1186 if [ ! -r "$failFile" ] ; then 1187 echo 1188 echo "--Done: test passed" 1189 exit 0 1190 else 1191 ls -l "$failFile" >&2 1192 echo "<pass:_begin_failFile_contents>" >&2 1193 cat "$failFile" >&2 1194 echo "<pass:_end_failFile_contents>" >&2 1195 fi 1196 } 1197 1198 runit() 1199 { 1200 setup 1201 docompile 1202 startJdb 1203 startDebuggee 1204 waitForFinish 1205 1206 # in hs_err file from 1.3.1 1207 debuggeeFailIfPresent "Virtual Machine Error" 1208 1209 # in hs_err file from 1.4.2, 1.5: An unexpected error 1210 debuggeeFailIfPresent "An unexpected error" 1211 1212 # in hs_err file from 1.4.2, 1.5: Internal error 1213 debuggeeFailIfPresent "Internal error" 1214 1215 1216 # Don't know how this arises 1217 debuggeeFailIfPresent "An unexpected exception" 1218 1219 # Don't know how this arises 1220 debuggeeFailIfPresent "Internal exception" 1221 }