This version looks good! Thanks for hanging in there. The only improvement would be to count and verify the number of ModificationWatchpointEvent (there should be 10).
Thanks, /Staffan On 13 feb 2014, at 21:15, shanliang <shanliang.ji...@oracle.com> wrote: > Hi, > > Here is Version 4: > http://cr.openjdk.java.net/~sjiang/JDK-8007710/04/ > > 1) remove the line > 108 vm.resume() > 2) call addClassWatch(vm) only when receiving VMStartEvent > 3) make sure that the test receives ModificationWatchpointEvent > 4) clean > > Thanks, > Shanliang > > shanliang wrote: >> >> Staffan, >> >> Very nice analysis! >> >> The fix must be very simple, just remove the line >> 108 vm.resume >> it is an error because here the test does not yet treat the events in >> eventSet. >> >> the line >> 136 eventSet.resume(); >> is the right place to resume the threads after event treatment. >> >> Here is the new webrev: >> http://cr.openjdk.java.net/~sjiang/JDK-8007710/03/ >> >> Thanks, >> Shanliang >> >> Staffan Larsen wrote: >>> >>> I think I understand what happens now. >>> >>> The test code, simplified, looks like this (with the Thread.sleep() added >>> that causes the test to fail): >>> >>> launchTarget(); >>> addClassWatch(); >>> vm.resume(); >>> Thread.sleep(1000); >>> while(connected) { >>> eventSet = eventQueue.remove() >>> for(event : eventQueue) { >>> if (event instanceof ClassPrepareEvent) { >>> addFieldWatch(); >>> } >>> } >>> eventSet.resume(); >>> } >>> >>> By default all events that happen will cause the debuggee to suspend (see >>> EventRequest.setSuspendPolicy()). Thus when we get to addFieldWatch(), the >>> vm should be suspended and we should be able to create the field watch >>> without problem. But the VM isn’t suspended and that is why the test fail. >>> >>> Why isn’t the VM suspended? When we get to the “for(event : eventQueue)” >>> the first time there are *two* events already in the queue: the >>> VMStartEvent and a ClassPrepareEvent. At this point the VM is suspended and >>> everything is good. We look at the first eventSet which only contains the >>> VMStartEvent, we ignore the event, but we resume the VM. We then loop and >>> look at the ClassPrepareEvent, but by now the VM is already running and has >>> also terminated. Failure. >>> >>> Thus, we need to handle the VMStartEvent. I suggest a modification to my >>> previous code: >>> >>> launchTarget(); >>> while(connected) { >>> eventSet = eventQueue.remove() >>> for(event : eventQueue) { >>> if (event instanceof VMStartEvent) { >>> addClassWatch(); >>> } >>> if (event instanceof ClassPrepareEvent) { >>> addFieldWatch(); >>> } >>> } >>> eventSet.resume(); >>> } >>> >>> This will cause us to have complete control over the state of the debuggee. >>> The first event we see will be the VMStartEvent. The VM will be suspended. >>> We can add a class watch here. Then we resume the VM. The second event we >>> see will be the ClassPrepareEvent with the VM suspended. We can add the >>> field watch. Then we resume the VM and wait for the field watch events. >>> >>> Thanks, >>> /Staffan >>> >>> On 13 feb 2014, at 11:36, shanliang <shanliang.ji...@oracle.com> wrote: >>> >>>> Staffan Larsen wrote: >>>>> >>>>> On 13 feb 2014, at 10:17, Jaroslav Bachorik >>>>> <jaroslav.bacho...@oracle.com> wrote: >>>>> >>>>> >>>>>> Hi Staffan, >>>>>> >>>>>> On 12.2.2014 18:27, Staffan Larsen wrote: >>>>>> >>>>>>> I’m still not happy with this fix since I think the extra output stream >>>>>>> synchronization logic is not needed - the debuggee should be suspended >>>>>>> at all the interesting points. The fix I proposed is cleaner and (as >>>>>>> far as I can tell) also fixes the problem. The only thing is that I >>>>>>> can’t quite explain what goes wrong without the fix… I’d really like to >>>>>>> understand that. I’ll try to dig deeper and see if I can understand >>>>>>> exactly what happens. >>>>>>> >>>>>> Yes, bringing the VM to a stable state before calling other JDI >>>>>> functions helps to stabilize the test even without the additional >>>>>> synchronization via stdout/stdin. >>>>>> >>>>>> I just wonder whether this check should not be done inside >>>>>> com.sun.jdi.connect.LaunchingConnector#launch() implementation. Does it >>>>>> even make sense to hand off an unstable VM? >>>>>> >>>>> Good question, but hard to change now - all implementations depend on the >>>>> current functionality. The VMStartEvent also gives you a reference to the >>>>> main thread. >>>>> >>>> The test failed when it received ClassPrepareEvent and did addFieldWatch, >>>> that meant the test must receive already VMStartEvent, because >>>> VMStartEvent must be the first event, if it was true then the vm must be >>>> already stable when failing. >>>> >>>> Except that the test received ClassPrepareEvent before VMStartEvent then >>>> it was doing addFieldWatch with a possibly unstable VM. in this case we >>>> might have a serious bug in VirtualMachine implementation, and if this is >>>> true the fix proposed to check "start" may make miss ClassPrepareEvent, >>>> then the test would test nothing. >>>> >>>> Shanliang >>>>> /S >>>>> >>>>> >>>>>> -JB- >>>>>> >>>>>> >>>>>>> /Staffan >>>>>>> >>>>>>> On 12 feb 2014, at 18:04, shanliang <shanliang.ji...@oracle.com> wrote: >>>>>>> >>>>>>> >>>>>>>> Staffan Larsen wrote: >>>>>>>> >>>>>>>>> I think what you need to do is wait for the VMStartEvent before you >>>>>>>>> add requests to the VM. Note this paragraph from the VirtualMachine >>>>>>>>> doc: >>>>>>>>> >>>>>>>>> Note that a target VM launched by a launching connector is not >>>>>>>>> guaranteed to be stable until after the VMStartEvent has been >>>>>>>>> received. >>>>>>>>> >>>>>>>>> >>>>>>>> I may miss something here, I believe VMStartEvent must be the first >>>>>>>> event, when the test got ClassPrepareEvent, it must already received >>>>>>>> VMStartEvent. >>>>>>>> >>>>>>>>> I think adding code that looks something like this will make the test >>>>>>>>> stable: >>>>>>>>> >>>>>>>>> VirtualMachine vm = launchTarget(CLASS_NAME); >>>>>>>>> EventQueue eventQueue = vm.eventQueue(); >>>>>>>>> >>>>>>>>> boolean started = false; >>>>>>>>> while(!started) { >>>>>>>>> EventSet eventSet = eventQueue.remove(); >>>>>>>>> for (Event event : eventSet) { >>>>>>>>> if (event instanceof VMStartEvent) { >>>>>>>>> started = true; >>>>>>>>> } >>>>>>>>> if (event instanceof VMDeathEvent >>>>>>>>> || event instanceof VMDisconnectEvent) { >>>>>>>>> throw new Error("VM died before it started...:"+event); >>>>>>>>> } >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> System.out.println("Vm launched"); >>>>>>>>> >>>>>>>>> >>>>>>>> The code you proposed could improve the test, it made sure that >>>>>>>> TestPostFieldModification was started, but I am afraid that it did not >>>>>>>> address the issue causing the failure, the issue I believe was that >>>>>>>> TestPostFieldModification exited before or during FieldMonitor called >>>>>>>> addFieldWatch(), that was why addFieldWatch() received >>>>>>>> VMDisconnectedException. When the test was treating ClassPrepareEvent, >>>>>>>> even if VMDeathEvent or VMDisconnectEvent arrived, it must be still >>>>>>>> waiting in the eventQueue because it arrived after ClassPrepareEvent. >>>>>>>> >>>>>>>> My fix was to not allow TestPostFieldModification to exit before >>>>>>>> addFieldWatch() was done. >>>>>>>> >>>>>>>>> There is also no reason to call addFieldWatch() before the >>>>>>>>> ClassPrepareEvent has been received. The call to vm..classesByName() >>>>>>>>> will just return an empty list anyway. >>>>>>>>> >>>>>>>>> >>>>>>>> I do not know why the test called addFieldWatch before >>>>>>>> ClassPrepareEvent had been received, but yes the returned list was >>>>>>>> empty, so agree to remove it. >>>>>>>> >>>>>>>>> While you are in there you can also remove the unused StringBuffer >>>>>>>>> near the top of main(). >>>>>>>>> >>>>>>>>> >>>>>>>> Yes it was already removed in version 01 >>>>>>>> >>>>>>>> Here is the new webrev: >>>>>>>> http://cr.openjdk.java.net/~sjiang/JDK-8007710/02/ >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Shanliang >>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> /Staffan >>>>>>>>> >>>>>>>>> On 11 feb 2014, at 18:30, shanliang <shanliang.ji...@oracle.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> Here is the new fix in which FieldMonitor will write to >>>>>>>>>> TestPostFieldModification, to inform the latter to quit, as >>>>>>>>>> suggested bu Jaroslav >>>>>>>>>> http://cr.openjdk.java.net/~sjiang/JDK-8007710/01/ >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>>> Shanliang >>>>>>>>>> >>>>>>>>>> shanliang wrote: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>> shanliang wrote: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Jaroslav Bachorik wrote: >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> On 11.2.2014 16:31, shanliang wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> Staffan Larsen wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Hi Shanliang, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I can’t quite see how the test can fail in this way. When the >>>>>>>>>>>>>>> ClassPrepareEvent happens, the debuggee will be suspended. So >>>>>>>>>>>>>>> when >>>>>>>>>>>>>>> addFieldWatch() is called, the debuggee should not have moved. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>> I am not expert of jdi so I may miss something here. I checked >>>>>>>>>>>>>> the >>>>>>>>>>>>>> failure trace and saw the report exception happen when >>>>>>>>>>>>>> FieldMonitor >>>>>>>>>>>>>> received ClassPrepareEvent and was doing addFieldWatch. >>>>>>>>>>>>>> FieldMonitor did >>>>>>>>>>>>>> call "vm.resume()" before treating events. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> AFAICS, calling vm.resume() results in an almost immediate >>>>>>>>>>>>> debuggee death. The gc() invoking thread "d" is flagged as a >>>>>>>>>>>>> deamon and as such doesn't prevent the process from exiting. The >>>>>>>>>>>>> other thread is not a daemon but will finish in only few cycles. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> I looked at the class com.sun.jdi.VirtualMachine, here is the >>>>>>>>>>>> Javadoc of the method "resume": >>>>>>>>>>>> /** >>>>>>>>>>>> * Continues the execution of the application running in this >>>>>>>>>>>> * virtual machine. All threads are resumed as documented in >>>>>>>>>>>> * {@link ThreadReference#resume}. >>>>>>>>>>>> * >>>>>>>>>>>> * @throws VMCannotBeModifiedException if the VirtualMachine is >>>>>>>>>>>> read-only - see {@link VirtualMachine#canBeModified()}. >>>>>>>>>>>> * >>>>>>>>>>>> * @see #suspend >>>>>>>>>>>> */ >>>>>>>>>>>> void resume(); >>>>>>>>>>>> My understanding is that the debuggee resumes to work after this >>>>>>>>>>>> call, instead to die? >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> In fact the problem is here, the vm (TestPostFieldModification) >>>>>>>>>>> should not die before FieldMonitor finishes addFieldWatch. >>>>>>>>>>> >>>>>>>>>>> Shanliang >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>>>> I reproduced the bug by add sleep(1000) after vm.resume() but >>>>>>>>>>>>>> before >>>>>>>>>>>>>> calling eventQueue.remove(); >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> It looks like some kind of synchronization between the debugger >>>>>>>>>>>>> and the debuggee is necessary. But I wonder if you should better >>>>>>>>>>>>> use the process.getOuptuptStream() to write and flush a message >>>>>>>>>>>>> for the debugee indicating that it can exit. And in the debugee >>>>>>>>>>>>> you would just do System.in.read() as the last statement in the >>>>>>>>>>>>> main() method. Seems more robust than involving files. >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> It could work, but creating a file in the testing directory should >>>>>>>>>>>> have no issue, but yes maybe less performance. >>>>>>>>>>>> >>>>>>>>>>>> Thanks, >>>>>>>>>>>> Shanliang >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> Cheers, >>>>>>>>>>>>> >>>>>>>>>>>>> -JB- >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>> Shanliang >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>>> One problem I do see with the test is that it does not wait for >>>>>>>>>>>>>>> a >>>>>>>>>>>>>>> VMStartEvent before setting up requests. I’m not sure if that >>>>>>>>>>>>>>> could >>>>>>>>>>>>>>> cause the failure in the bug report, though. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> /Staffan >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On 11 feb 2014, at 15:13, shanliang >>>>>>>>>>>>>>> <shanliang.ji...@oracle.com> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Hi , >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The problem could be that FieldMonitor did not have enough >>>>>>>>>>>>>>>> time to >>>>>>>>>>>>>>>> "addFieldWatch" but the vm to monitor >>>>>>>>>>>>>>>> (TestPostFieldModification) was >>>>>>>>>>>>>>>> already ended. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> So we should make sure that TestPostFieldModification exits >>>>>>>>>>>>>>>> after >>>>>>>>>>>>>>>> FieldMonitor has done necessary. The solution proposed here is >>>>>>>>>>>>>>>> that >>>>>>>>>>>>>>>> FieldMonitor creates a file after adding field watching, and >>>>>>>>>>>>>>>> TestPostFieldModification quits only after finding the file. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> web: >>>>>>>>>>>>>>>> http://icncweb.fr.oracle.com/~shjiang/webrev/8007710/00/ >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> bug: >>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8007710 >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Thanks, >>>>>>>>>>>>>>>> Shanliang >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>> >>>>>>> >>>>> >>>> >>>> >>> >> >