[squeak-dev] logging to Transcript from not-UI process

Levente Uzonyi leves at caesar.elte.hu
Sun Sep 13 21:15:19 UTC 2020


Hi Tim,

On Sun, 13 Sep 2020, tim Rowledge wrote:

> The recent discussions about change logs etc, along with thinking about how the Toothpick package might do the job better (just realised that one could add an MQTT logger to it so that clusters of images could simply publish the logs and 'normal' tools could be used for sysadmin purposes) have reminded of a problem that has bitten me a couple of times over the last few weeks.
>
> Basically, if we have a non-UI process (like Seaside handling) that tries to send something to the Transcript, then just occasionally and always, of course, during a demo, it will cause a problem. Obviously, I can't find a log file of it happening to illustrate; that would be far to helpful. IIRC it's something relating to the re-layout phase of the text morph.
>
> Now I'd swear (and did!) that we 'fixed' this several years ago but I can't find any email about it so maybe I'm just hallucinating again.
>
> Has anybody else seen this, or can remember about it or... ?

Only the #endEntry message is protected against concurrent access, so 
you can't write anything in a thread-safe manner outside the UI process.

I would say it was written with a single process in mind, and later 
"patched" to be able to "handle" concurrent access.

My workaround is that whenever I need to log something to the Transcript 
from potentially another process, I prepare the string to log in my 
process then use #addDeferredUIMessage: to inject it into the UI process 
in a safe way. E.g.

Transcript open.
[
         | message |
         message := 'This is a very {1} log message at {2}.' format: { 
'important'. DateAndTime now
}.
         Project current addDeferredUIMessage: [ Transcript nextPutAll:
message; cr; endEntry ] ] fork.

What I've been thinking about in the past decade is to add new formatting 
messages to TranscriptStream. E.g. #show:formattedWith:, which does what 
the above thing would but you could just send it to Transcript directly, 
like:

Transcript show: 'This is a very {1} log message at {2}.{3}' formattedWith: { 'important'. DateAndTime now. String cr }

Or #showStream:, which would let you safely write a message on a stream. 
E.g.:

Transcript showStream: [ :stream | stream nextPutAll: 'foo'; nextPutAll: 'bar'; cr ].

However, that would require a few changes like turning AccessSema into a 
Mutex to be reentrant. (also, why is AccessSema a class variable used by 
an instance?)

#nextPut:, #nextPutAll: and all the other Stream API exposed by 
inheritance are useless, because tThey can't be made concurrent unless 
they are all overridden.
So, IMHO TranscriptStream should be replaced with a new class inheriting 
from Object, containing a single WriteStream, and providing a 
thread-safe API (which can be the same as the current one).


Levente

>
> tim
> --
> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim
> Java:  the best argument for Smalltalk since C++


More information about the Squeak-dev mailing list