[squeak-dev] Transcript error when forceUpdate: false (?)

Marcel Taeumel marcel.taeumel at hpi.de
Wed Jan 27 08:41:08 UTC 2021


Hi Eliot.

Thanks for the clarification of VM suspension points.

> So let's please use the proper construct, Mutex.

Hmmm. I suppose it's not that easy. If #endEntry is running inside the ui process, we must not wait to not block the ui process (given that we want to implement #forceUpdate) -- but instead complete all deferred messages or just trigger a drawing cycle. A simple mutex wouldn't do because we want to avoid context switching altogether while executing methods that use such process comparision.

Thread-safety might be an issue in several places, which kind of use "Processor activeProcess == Project current uiProcess":

MorphicProject >> #spawnNewProcessIfThisIsUI:
(Morphic|MVC)Debugger class >> #openOn:...

Even there, a mutex would not do because we want to avoid comparing the wrong objects, not to avoid reentering that section. The entire expression "Processor activeProcess == Project current uiProcess" should be atomic.

> Any unused numeric primitive could be used as a marker to avoid context switches.  I propose that we use it, hiding it behind a suitable pragma for syntactic sugar (i.e. <noContextSwitch>).  123 used to be primitiveValueUninteruptibly, which we no longer use.  I propose we use this.

+1 :-)

Best,
Marcel
Am 27.01.2021 01:35:09 schrieb Eliot Miranda <eliot.miranda at gmail.com>:


On Tue, Jan 26, 2021 at 2:45 PM Eliot Miranda <eliot.miranda at gmail.com [mailto:eliot.miranda at gmail.com]> wrote:

Hi Marcel, Hi All,


On Mon, Jan 25, 2021 at 3:26 AM Marcel Taeumel <marcel.taeumel at hpi.de [mailto:marcel.taeumel at hpi.de]> wrote:

> It's simply not thread-safe.

Hmm... in particular, there is a side effect (i.e. layout update) in the window's pluggable text morph. Even if #forceUpdate is false.

In #endEntry, we could check for "Processor activeProcess == Project current uiProcess" to then use "Project current addDeferredUIMessage..." automatically.

That gave me a scare.  At first I thought that the effectiveProcess changes to ProcessorScheduler>>activeProcess could have made that expression no longer thread safe.  But it isn't anyway, and the above is very bad style.  Let me explain.

The suspension points in the VM are 
- the first bytecode of any non-quick method (following a primitive if it has one)
- the first bytecode of any block
- a backward branch

In the JIT there are fewer suspension points:
- the first bytecode of any method containing a send other than #== and/or #class (and given that ifNil:ifNotNil: is inlined into a send of #== and jumps, ifNil: sends don't count)
- the first bytecode of any block containing a send other than #== and/or #class
- a backward branch

So given

ProcessorScheduler>>#activeProcess
        "suspension point here on an interpreter VM, and the first time in the JIT VM"
^activeProcess effectiveProcess

Process>>#effectiveProcess
        "suspension point here on an interpreter VM, and the first time in the JIT VM"
^effectiveProcess ifNil: [self]

Project class>>#current
        "suspension point here on an interpreter VM, and the first time in the JIT VM"
^CurrentProject

MVCProject>>#uiProcess

        "suspension point here on an interpreter VM, and the first time in the JIT VM"
^ world activeControllerProcess


MorphicProject>>#uiProcess
        "no suspension point here on any VM obeying the blue-book spec"
^uiProcess

we can see that "Processor activeProcess == Project current uiProcess" is not thread-safe in the interpreter; there is a suspension point in Project current before CurrentProject is returned (but not in the JIT); there is a suspension point in MVC in uiProcess.  There is a suspension point in ProcessorScheduler>>#activeProcess before the send of effectiveProcess to activeProcess, but since no data is fetched until the process resumes this is harmless.  However, were the expression written as "Project current uiProcess == Processor activeProcess" then this would no longer be harmless.


So on all VMs this is not reliably thread-safe.  Even on the JIT VM the first use of any method (except a doit) is interpreted.  Once the JIT VM, once it has started up and the methods have been jitted, "Processor activeProcess == Project current uiProcess" is thread-safe on Morphic, but not on MVC.  So we really shouldn't be using things like this.  They'll appear to work and in very rare circumstances they won't.  So let's please use the proper construct, Mutex.


But that makes me realize that the effectiveProcess changes are unsafe on an interpreter VM (and hence we're on;y getting away with it on the JIT VM).  Se really need some way of saying that ProcessorScheduler>>#activeProcess is atomic, e.g.

Process>>#effectiveProcess
        <noContextSwitch>
^effectiveProcess ifNil: [self]

But I don't know how to implement this right now.  Note that we do have 

BlockClosure>>#valueNoContextSwitch
"An exact copy of BlockClosure>>value except that this version will not preempt
the current process on block activation if a higher-priority process is runnable.
Primitive. Essential."
<primitive: 221>
numArgs ~= 0 ifTrue:
[self numArgsError: 0].
self primitiveFailed

FullBlockClosure>>#valueNoContextSwitch
"An exact copy of BlockClosure>>value except that this version will not preempt
the current process on block activation if a higher-priority process is runnable.
Primitive. Essential."
<primitive: 209>
numArgs ~= 0 ifTrue:
[self numArgsError: 0].
self primitiveFailed

but the VM uses the primitive numbers to control context switching.  We don't have a mechanism the VM can use to label a normal method such as Process>>#effectiveProcess as not to allow an interrupt.

Doh!  We have primitive numbers.  We already use primitive 19 as a "simulation guard" in the debugger machinery as a "simulation guard" to avoid I'm not sure what.  Any unused numeric primitive could be used as a marker to avoid context switches.  I propose that we use it, hiding it behind a suitable pragma for syntactic sugar (i.e. <noContextSwitch>).  123 used to be primitiveValueUninteruptibly, which we no longer use.  I propose we use this.

Best,

Marcel
Am 23.01.2021 21:05:05 schrieb Levente Uzonyi <leves at caesar.elte.hu [mailto:leves at caesar.elte.hu]>:
On Fri, 22 Jan 2021, tim Rowledge wrote:

>
>
>> On 2021-01-22, at 5:26 PM, David T. Lewis wrote:
>>
>> On Fri, Jan 22, 2021 at 02:03:10PM -0600, jaromir wrote:
>>> I ran the following in Squeak 5.3:
>>>
>>> TranscriptStream forceUpdate: false.
>>> [ 10000 timesRepeat: [ Transcript show: 'x' ] ] forkAt: 39
>>>
>>> When the Transcript window fills up, 'Message not understood' and 'Assertion
>>> failure' appear. I'm wondering is this a bug? Thanks. Jaromir
>>>
>>>
>>>
>>
>> It certainly does appear to be a bug.
>
> We had some discussion about it not so long ago; you can't use the Transcript to log bugs from Seaside very well, for example. Background processes, mutexs, that sort of thing. IIRC Levente offered an explanation?

It's simply not thread-safe.
If you want it to be thread-safe, you can pass your message to the UI
process to show it. Make sure your message is computed in its own process
and is passed as a precomputed string to avoid other kinds of race
conditions. E.g.:

| theMessage |
theMessage := 'Something very {1}.' format: { 'important' }.
Project current addDeferredUIMessage: [ Transcript show: theMessage; cr ].


Levente

>
>
> tim
> --
> tim Rowledge; tim at rowledge.org [mailto:tim at rowledge.org]; http://www.rowledge.org/tim [http://www.rowledge.org/tim]
> The hardness of the butter is proportional to the softness of the bread.





--

_,,,^..^,,,_

best, Eliot


--

_,,,^..^,,,_

best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20210127/89968b1f/attachment-0001.html>


More information about the Squeak-dev mailing list