problem debugging <Over> - correctly sequencing debug of multi-threaded code per process priorities

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

problem debugging <Over> - correctly sequencing debug of multi-threaded code per process priorities

Ben Coman
I'm not sure if I'm doing the wrong thing, or if I've bumped into a problem with step <Over>.
I'm trying to add some debugging support into multi-threaded code to help properly sequence debugging different priority processes. I've extracted a little demo...

TestCase subclass: #Example
instanceVariableNames: 'doCycle debug highPriorityProcess'
classVariableNames: ''
package: 'KernelX-DelayScheduler'


Example >> highPriorityCycle
debug ifTrue: [ self halt ].
Transcript show: 'H'.


Example
  >> highPriorityRunLoop
doCycle := Semaphore new.
^[ [ doCycle wait.
self highPriorityCycle ] repeat.
] forkAt: 45 named: 'Example high side'


Process >> isWaiting
^myList isKindOf: Semaphore


Example >>  wakeHighPriorityLoop
doCycle signal.
debug ifTrue: [  "wait until high priority process is sleeping"
[ highPriorityProcess isWaiting & highPriorityProcess isTerminated not] 
whileFalse: [ 
Transcript show: '.'. 
100 milliSeconds wait ].
self halt
].


Example >>  testUserPriority
debug := true.
highPriorityProcess := self highPriorityRunLoop.
Transcript cr.
debug ifTrue: [self halt].
3 timesRepeat: [ 
Transcript crShow: 'U'. 
self wakeHighPriorityLoop.].
highPriorityProcess terminate.


Running #testUserPriority, on Transcript you'll see....
UH
UH
UH

_______________
Changing "debug := true" and run  #testUserPriority
and the UI will lockup, until "TestTookTooMuchTime" appears.
But it works with the following change...

ClyRunTestsFromMethodsCommand >> runTest: testSelector of: testClass
[
| testResult |
testResult := testClass debug: testSelector.
self
notifyUserAboutResults: testResult 
with: 'Method: ' , testClass asString , '>>#' , testSelector asString
] forkNamed: 'TESTING ' , testClass asString , '>>#' , testSelector asString


Now running #testUserPriority and pressing <Proceed> 
at each pre-debug window gives the following result...

U................H
U..............H
U............H


It also works properly to run  #testUserPriority and debug <Into> #wakeHighPriorityLoop
initially ignoring the #highPriorityCycle pre-debug that pops up 
to step around the #whileFalse: loop a few times. 
Then <Proceed>ing the  #highPriorityCycle pre-debug
and stepping until out of  #wakeHighPriorityLoop.
Works fine. 


However running  #testUserPriority, debugging into #wakeHighPriorityLoop
but stepping <Over>  #wakeHighPriorityLoop
locks up the UI, and I can't tell why.

Can anyone advise?

cheers -ben

P.S. What I'm trying to do it make it easier for others to trace the operation of the delay scheduler to understand its unit tests.
Reply | Threaded
Open this post in threaded view
|

Re: problem debugging <Over> - correctly sequencing debug of multi-threaded code per process priorities

Ben Coman


On 13 June 2018 at 11:46, Ben Coman <[hidden email]> wrote:
I'm not sure if I'm doing the wrong thing, or if I've bumped into a problem with step <Over>.
I'm trying to add some debugging support into multi-threaded code to help properly sequence debugging different priority processes. I've extracted a little demo...

TestCase subclass: #Example
instanceVariableNames: 'doCycle debug highPriorityProcess'
classVariableNames: ''
package: 'KernelX-DelayScheduler'


Example >> highPriorityCycle
debug ifTrue: [ self halt ].
Transcript show: 'H'.


Example
  >> highPriorityRunLoop
doCycle := Semaphore new.
^[ [ doCycle wait.
self highPriorityCycle ] repeat.
] forkAt: 45 named: 'Example high side'


Process >> isWaiting
^myList isKindOf: Semaphore


Example >>  wakeHighPriorityLoop
doCycle signal.
debug ifTrue: [  "wait until high priority process is sleeping"
[ highPriorityProcess isWaiting & highPriorityProcess isTerminated not] 
whileFalse: [ 
Transcript show: '.'. 
100 milliSeconds wait ].
self halt
].


Example >>  testUserPriority
debug := true.

Sorry, the above line should have been "debug := false" and this stage of the post.
cheers -ben
 
highPriorityProcess := self highPriorityRunLoop.
Transcript cr.
debug ifTrue: [self halt].
3 timesRepeat: [ 
Transcript crShow: 'U'. 
self wakeHighPriorityLoop.].
highPriorityProcess terminate.


Running #testUserPriority, on Transcript you'll see....
UH
UH
UH

_______________
Changing "debug := true" and run  #testUserPriority
and the UI will lockup, until "TestTookTooMuchTime" appears.
But it works with the following change...

ClyRunTestsFromMethodsCommand >> runTest: testSelector of: testClass
[
| testResult |
testResult := testClass debug: testSelector.
self
notifyUserAboutResults: testResult 
with: 'Method: ' , testClass asString , '>>#' , testSelector asString
] forkNamed: 'TESTING ' , testClass asString , '>>#' , testSelector asString


Now running #testUserPriority and pressing <Proceed> 
at each pre-debug window gives the following result...

U................H
U..............H
U............H


It also works properly to run  #testUserPriority and debug <Into> #wakeHighPriorityLoop
initially ignoring the #highPriorityCycle pre-debug that pops up 
to step around the #whileFalse: loop a few times. 
Then <Proceed>ing the  #highPriorityCycle pre-debug
and stepping until out of  #wakeHighPriorityLoop.
Works fine. 


However running  #testUserPriority, debugging into #wakeHighPriorityLoop
but stepping <Over>  #wakeHighPriorityLoop
locks up the UI, and I can't tell why.

Can anyone advise?

cheers -ben

P.S. What I'm trying to do it make it easier for others to trace the operation of the delay scheduler to understand its unit tests.

Reply | Threaded
Open this post in threaded view
|

Re: problem debugging <Over> - correctly sequencing debug of multi-threaded code per process priorities

Ben Coman
In reply to this post by Ben Coman


On 13 June 2018 at 11:46, Ben Coman <[hidden email]> wrote:
I'm not sure if I'm doing the wrong thing, or if I've bumped into a problem with step <Over>.
I'm trying to add some debugging support into multi-threaded code to help properly sequence debugging different priority processes. I've extracted a little demo...

TestCase subclass: #Example
instanceVariableNames: 'doCycle debug highPriorityProcess'
classVariableNames: ''
package: 'KernelX-DelayScheduler'


Example >> highPriorityCycle
debug ifTrue: [ self halt ].
Transcript show: 'H'.


Example
  >> highPriorityRunLoop
doCycle := Semaphore new.
^[ [ doCycle wait.
self highPriorityCycle ] repeat.
] forkAt: 45 named: 'Example high side'


Process >> isWaiting
^myList isKindOf: Semaphore


Example >>  wakeHighPriorityLoop
doCycle signal.
debug ifTrue: [  "wait until high priority process is sleeping"
[ highPriorityProcess isWaiting & highPriorityProcess isTerminated not] 
whileFalse: [ 
Transcript show: '.'. 
100 milliSeconds wait ].
self halt
].

To make this example simpler, I changed this method to...
Example >> wakeHighPriorityLoop
|count|
count := 0.
[ Transcript show: '.'.
count := count + 1.
count > 10 ifTrue: [^self].
200 milliSeconds wait.
  ] repeat.
 


Example >>  testUserPriority
debug := true.
highPriorityProcess := self highPriorityRunLoop.
Transcript cr.
debug ifTrue: [self halt].
3 timesRepeat: [ 
Transcript crShow: 'U'. 
self wakeHighPriorityLoop.].
highPriorityProcess terminate.

and this method to...
Example >>  testUserPriority
[ 3 timesRepeat: [ 
Transcript crShow: 'U'. 
self halt.
self wakeHighPriorityLoop.].
] forkAt: 39 named: 'testUserPriority'.
self halt.
highPriorityProcess terminate.  

So there should be no way that the 39-priority thread should block the 40-priority UI thread.
But when I run #testUserPriority and step <Over>  #wakeHighPriorityLoop
the UI blocks for two seconds and then all of a sudden  "U..........." appears in full on the Transcript shows.
I'd expect to see the dots slowly appearing one-by-one.
I really don't understand the behaviour I'm seeing.

cheers -ben