Bug 233319 - Initial JDIThread state can get out-of-sync with its underlying ThreadReference
Summary: Initial JDIThread state can get out-of-sync with its underlying ThreadReference
Status: NEW
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Debug (show other bugs)
Version: 3.4   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: JDT-Debug-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2008-05-21 15:11 EDT by Samantha Chan CLA
Modified: 2023-11-20 00:16 EST (History)
5 users (show)

See Also:


Attachments
patch to org.eclipse.jdt.debug (2.91 KB, patch)
2008-05-28 22:25 EDT, Samantha Chan CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Samantha Chan CLA 2008-05-21 15:11:58 EDT
When JDIThread is initialized, JDIThread sets its initial thread state based on its underlying ThreadReference's suspend state.  When this initialization is done, the underlying thread could be in a transient suspend state, causing the JDIThread to think that is is currently suspended.  When the VM later resumes the thread, JDWP does not provide any event notification about the change of thread state.  As a result, JDIThread will continue to report that it is suspended when it is not.

The side effect of this defect is that the Debug View may try to auto-expand and select the top stackframe from the suspended thread.  This will cause the "source not up" editor to show up since the thread is usually stopped at a place where the user does not have source for.
Comment 1 Samantha Chan CLA 2008-05-28 22:25:58 EDT
Created attachment 102556 [details]
patch to org.eclipse.jdt.debug

Hi Darin,

First attempt to keep the thread state in-sync.  This patch needs more testing, but I would like you to take a look and see if you agree with this approach.

The idea is that when the thread is first created, we record the creation time, and set a flag to indicate that the thread state can be wrong.  The flag is set if the thread is suspended initially.

We do not update the thread state if no one asks for it.  If no one asks for it, I assumes that the internal state is not important at the moment.  If JDIThread.isSuspended() is called, that means the thread state has become important.  If the flag is set, then we ask the underlying ThreadReference for the thread state again.  We keep checking until the thread has been created for more than 1000 ms.

I have tested this in my environment and seems to solve the problem that source lookup is done when the thread is temporarily suspended.  I need to test this more, but let me know what you think.

With this patch, the thread should always return the correct thread state when it is needed.

In addition, not done with this patch, but should we delay the handling of the thread create event, instead of delaying the install of the model proxy?  If we delay that for a bit, then we can wait for the thread state to settle down before spawning off the auto-expand job.

I need to know if this can be contained for RC3, and will try to provide an updated patch.

Thanks...
Sam
Comment 2 Darin Wright CLA 2008-05-29 09:53:35 EDT
Thanks for the patch, Sam. 

I think that the thread can still lie about its state. For example, if I take out to 500ms delay in the model proxy, then I still get the "Object" editor opening up. If someone calls isSuspended() before the VM has settled down, it does refresh state, but it can still retrieve the wrong transient state.
Comment 3 Samantha Chan CLA 2008-05-29 10:12:56 EDT
Agreed.  This does not fix the problem completly, but reduces the chance of JDIThread reporting wrong state when the thread state is needed.  It also helps us get around the problem with our debugger.

Here's what I did in my  model.  I am wondering if it should be pushed down to JDT to solve the problem.

When my thread is created, I ask JDIThread if it is suspended.  If it is suspended, then I schedule a job to check the state again.  The thread continues with its creation and fires CREATE debug event.  We assume the thread to be running at this time.  The job is scheduled with a 1000 ms delay.  In addition, the job has a scheduling rule to serialize on the target.  So, we check one thread at a time.  When the job is run, the the thread asks JDIThead if it is suspended again.  If it is, then it will fire a SUSPEND event.  The event detail is UNSPECIFIED to prevent all the threads from expanding.

I think the same logic may help with JDIThread.  So for JDIThread, when it is first created, JDIThread reports running when even though the ThreadReference thinks it's suspended.  In addition, JDIThread will schedule a job with a scheduling rule to serialize on the target.  When the job gets run, it refereshes the thread state.  If the thread is still suspended, then it should fire a suspend event.  Otherwise, nothing should be done.  If this fix is put into JDT, then my model does not have to schedule the job to check thread state again.  Instead, it can rely on a suspend event coming if the thread is really suspended.

I haven't tried it... but was thinking to try it next.  Thoughts?  
Comment 4 Darin Wright CLA 2008-06-04 10:53:47 EDT
Currently we have no fix in hand for this. There appears to be an issue with JDI/JDWP where initial thread states are reported as "isSuspended() = true", and the thread state is THREAD_STATE_WAITING. At this point, there are even stack frames in java.lang.Object.wait().

A short time later, the threads resume without notification. Since we can't rely on a VMStart event to be received, we can't wait to initialize threads until that point.

Marking as a 3.4.1 candidate.
Comment 5 Darin Wright CLA 2008-06-13 12:48:48 EDT
It appears that JDI/JDWP are telling the truth...

When we launch a VM for local debugging, we specify "suspend=y" for the debugger agent. This suspends all threads on startup until the debugger attaches and resumes the VM (in response to the VM start event). So, we see all threads as initially suspended, and we resume all threads when the VM start event is sent, and we update thread states to running - all states are correct.

Similarly when attaching to a VM, all thread states are correct.

The problem is that there is no way to tell that a VM Start event is pending and if an initial suspended thread state will be transient. The "suspend=y" command line option is a hint, but we don't always have access to the command line (e.g. remote server), and the option is only valid for the first attach to the VM (i.e. not on subsequent connects/disconnects).

To solve this problem, JDI/JDWP do not provide us with any help that I have been able to find - the VM Start event is not specified to occur, and I don't see an obcious way to determine that it will occur.
Comment 6 Darin Wright CLA 2008-07-29 11:15:42 EDT
Removing 3.4.1 target - there is no fix in hand for this problem.
Comment 7 Eclipse Genie CLA 2019-12-01 11:41:23 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 8 Sarika Sinha CLA 2019-12-09 01:16:10 EST
@Simeon,
If this interests you ?
Comment 9 Simeon Andreev CLA 2019-12-09 03:56:55 EST
(In reply to Sarika Sinha from comment #8)
> @Simeon,
> If this interests you ?

On first glance no. Our application uses only the Eclipse debugger, I'm not sure how a thread can be in suspended state before the Eclipse debugger is attached. Maybe some conditional breakpoint at some JRE method that spawns threads, so that the thread is suspended for a short amount of time close to spawning.

Our user base is not so advanced though; I doubt we'd have such complex scenarios. Andrey?
Comment 10 Andrey Loskutov CLA 2019-12-09 09:24:02 EST
(In reply to Simeon Andreev from comment #9)
> (In reply to Sarika Sinha from comment #8)
> > @Simeon,
> > If this interests you ?
> 
> On first glance no. Our application uses only the Eclipse debugger, I'm not
> sure how a thread can be in suspended state before the Eclipse debugger is
> attached. 

I see that we always use this argument below even if we start JVM locally:
agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:44162

See org.eclipse.jdt.internal.launching.StandardVMDebugger.getCommandLine(VMRunnerConfiguration, ILaunch, IProgressMonitor)

So initially JVM is in suspended state, so part 1 from comment 5 about local execution is still valid:

> It appears that JDI/JDWP are telling the truth...
> 
> When we launch a VM for local debugging, we specify "suspend=y" for the
> debugger agent. This suspends all threads on startup until the debugger
> attaches and resumes the VM (in response to the VM start event). So, we see
> all threads as initially suspended, and we resume all threads when the VM
> start event is sent, and we update thread states to running - all states are
> correct.

However, I believe we are here at the second part of the comment 5 about remote execution:

> Similarly when attaching to a VM, all thread states are correct.
> 
> The problem is that there is no way to tell that a VM Start event is pending
> and if an initial suspended thread state will be transient. The "suspend=y"
> command line option is a hint, but we don't always have access to the
> command line (e.g. remote server), and the option is only valid for the
> first attach to the VM (i.e. not on subsequent connects/disconnects).

And the last part of the comment 5 says:
 
> To solve this problem, JDI/JDWP do not provide us with any help that I have
> been able to find - the VM Start event is not specified to occur, and I
> don't see an obcious way to determine that it will occur.

So if this is still true, we have a possible problem with remote connecting. If I read it right, a workaround would be: we can disconnect & re-connect to get the Debug view to the "expected" state.

> Our user base is not so advanced though; I doubt we'd have such complex
> scenarios. Andrey?

I think we don't use remote Java debugging so far, so yes, this is probably unrelated to our product.

Given the age of the bug and no inputs so far from other users, I would not consider this as an urgent problem to fix.
Comment 11 Eclipse Genie CLA 2021-11-29 05:09:07 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 12 Eclipse Genie CLA 2023-11-20 00:16:30 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.