Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problem with vwait in threaded Tcl

126 views
Skip to first unread message

mark....@gmail.com

unread,
Jun 23, 2016, 4:31:09 AM6/23/16
to
I have inherited an old Tcl application that used to run happily in Tcl 8.4 on OpenSUSE 10.2. I am now trying to run it on more recent versions of OS and Tcl, and I'm finding that it gets stuck at a vwait. I have established that this is because I am now running with Tcl built with threading enabled, and I can make it work if I build Tcl without threading, but I have not found a solution that I can apply in the script itself.

A test script that reproduces the problem is:

---------------
proc myproc {} {
puts "hello"
}

set forever [eval myproc]
catch {vwait forever}

puts "the end"
---------------

With a non-threaded Tcl, I see both output messages and the process exits. This is the behaviour the application expects. With a threaded Tcl, I see "hello" but not "the end" and the process waits forever.

Could anyone advise on what I can change in the script to get the desired behaviour?

Thanks.

Christian Gollwitzer

unread,
Jun 23, 2016, 4:59:20 AM6/23/16
to
Am 23.06.16 um 10:31 schrieb mark....@gmail.com:
> ---------------
> proc myproc {} {
> puts "hello"
> }
>
> set forever [eval myproc]
> catch {vwait forever}
>
> puts "the end"
> ---------------
>
> With a non-threaded Tcl, I see both output messages and the process exits.

What is the intent of the real script? Your demonstration can be shortened:

catch {vwait forever}
puts End

The reason for the differing behaviour is, that in non-threaded Tcl
vwait can detect that it would literally wait forever, because there are
no pending events, and throws an error instead:

% vwait forever
can't wait for variable "forever": would wait forever

The error is caught, and the script goes on. Note that "forever" must be
written to *while* vwait is waiting, not before. If you change to

after 0 { set forever now}
vwait forever

the after event will terminate the vwait in all builds of Tcl.

In threaded Tcl, a second thread could actually queue an event and thus
vwait can not decide that it is uselessly waiting for Godot.

In short, the program above has a bug. It asks to wait endlessly,
without any possibility to end and while doing nothing. The bug surfaces
in different ways for threaded/non-threaded Tcl.

Christian

EL

unread,
Jun 23, 2016, 11:44:04 AM6/23/16
to
Am 23.06.16 um 10:59 schrieb Christian Gollwitzer:

> In short, the program above has a bug. It asks to wait endlessly,
> without any possibility to end and while doing nothing. The bug surfaces
> in different ways for threaded/non-threaded Tcl.

I had a similar issue lately. Funny that Tcl decides when a program
can/cannot run forever and not the programmer...
Anyway, if that is the issue, i.e. if the program really has no after or
other event loop commands, it is possible to simulate a fake event loop:


proc fake args {}
after 100 fake
vwait forever

puts "the end"


Not a state of the art solution, but it works.

--
EL

Christian Gollwitzer

unread,
Jun 23, 2016, 12:31:08 PM6/23/16
to
Am 23.06.16 um 17:30 schrieb EL:
> Am 23.06.16 um 10:59 schrieb Christian Gollwitzer:
>
>> In short, the program above has a bug. It asks to wait endlessly,
>> without any possibility to end and while doing nothing. The bug surfaces
>> in different ways for threaded/non-threaded Tcl.
>
> I had a similar issue lately. Funny that Tcl decides when a program
> can/cannot run forever and not the programmer...

Yes, but what's the point? If there is no pending event, and no second
thread, and no Tk - what does the vwait do? Just occupying memory? Until
proven otherwise, I believe that this is always a bug in the script.

Christian

EL

unread,
Jun 23, 2016, 1:22:04 PM6/23/16
to
Am 23.06.16 um 18:31 schrieb Christian Gollwitzer:

> Yes, but what's the point? If there is no pending event, and no second
> thread, and no Tk - what does the vwait do? Just occupying memory? Until
> proven otherwise, I believe that this is always a bug in the script.

In my case: I want to start an interpreter, load the comm extension,
print the comm id and then wait forever for connections from another
interp. Then I want to connect from another interp and run commands in
the first one.
So, the first interp is meant to act as a "comm server", but funny
enough it doesn't go into the event loop by just "package re comm".

The use case arises with my new comm REPL feature in Tloona, which
provides a way to run commands in a REPL that is attached to an external
interpreter via comm. (Version 1.7.1 here
https://fossil.e-lehmann.de/tloona/wiki?name=Downloads+and+Release+Notes
)

Finally I needed this feature for attaching Jtcl. And it happens that
Jtcl has the event loop always activated, so I don't need a fake event
loop there...


--
EL

Robert Heller

unread,
Jun 23, 2016, 2:02:07 PM6/23/16
to
At Thu, 23 Jun 2016 19:18:45 +0200 EL <elehm...@gmail.com> wrote:

>
> Am 23.06.16 um 18:31 schrieb Christian Gollwitzer:
>
> > Yes, but what's the point? If there is no pending event, and no second
> > thread, and no Tk - what does the vwait do? Just occupying memory? Until
> > proven otherwise, I believe that this is always a bug in the script.
>
> In my case: I want to start an interpreter, load the comm extension,
> print the comm id and then wait forever for connections from another
> interp. Then I want to connect from another interp and run commands in
> the first one.
> So, the first interp is meant to act as a "comm server", but funny
> enough it doesn't go into the event loop by just "package re comm".

Doing a 'package require ...' is almost *never* going to start an event loop.
The *only* expection is 'package require Tk', and that is only because it
connects to the XLib and creates the main window (.). It is always going to
be necessary to do the comm equivalent of:

socket -server server 9999
proc server {channel address port} {
...
}

vwait forever



>
> The use case arises with my new comm REPL feature in Tloona, which
> provides a way to run commands in a REPL that is attached to an external
> interpreter via comm. (Version 1.7.1 here
> https://fossil.e-lehmann.de/tloona/wiki?name=Downloads+and+Release+Notes
> )
>
> Finally I needed this feature for attaching Jtcl. And it happens that
> Jtcl has the event loop always activated, so I don't need a fake event
> loop there...
>
>

--
Robert Heller -- 978-544-6933
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services
hel...@deepsoft.com -- Webhosting Services

Rich

unread,
Jun 23, 2016, 3:27:34 PM6/23/16
to
I suspect that EL's point might be that if he wants to do the
equivalent of this in BASIC:

10 GOTO 10

Then that's his perogative.

At the same time, I'm on your side for what Tcl does, I'd rather be
alerted that I've created by accident the equivalent of "10 GOTO 10"
rather than watching a script do nothing, with no warning.

Rich

unread,
Jun 23, 2016, 3:35:59 PM6/23/16
to
EL <elehm...@gmail.com> wrote:
> Am 23.06.16 um 18:31 schrieb Christian Gollwitzer:
>
>> Yes, but what's the point? If there is no pending event, and no second
>> thread, and no Tk - what does the vwait do? Just occupying memory? Until
>> proven otherwise, I believe that this is always a bug in the script.
>
> In my case: I want to start an interpreter, load the comm extension,
> print the comm id and then wait forever for connections from another
> interp. Then I want to connect from another interp and run commands in
> the first one.
> So, the first interp is meant to act as a "comm server", but funny
> enough it doesn't go into the event loop by just "package re comm".

No, comm does not go "into the event loop" via package require. You
have to activate an event loop manually if you are not already inside
an environment (Tk) that starts one by default.

But because comm sets up a fileevent on the default 'comm' TCP port,
there is a way for events to be generated, so you can use "vwait
forever" (or your choice of "forever" variable name) to start an event
loop manually in a plain Tcl script.

mark....@gmail.com

unread,
Jun 27, 2016, 11:44:43 AM6/27/16
to
Christian - thanks for the explanation. The real script does a lot of things that I don't fully understand yet - partly because it's huge but also because I'm new to Tcl. In essence, it runs a separate 'make' process with the stdout/stderr processed by a Tcl proc. The main script is supposed to just wait for the make to complete, then exit itself.

I have tried 'after 0', with mixed results, but I think I'd better wait until I understand the whole thing better before posting potentially time-wasting newbie questions.

Thanks again.

Alexandre Ferrieux

unread,
Jun 27, 2016, 7:14:07 PM6/27/16
to
On Monday, June 27, 2016 at 5:44:43 PM UTC+2, mark....@gmail.com wrote:
>
> [...] but I think I'd better wait until I understand the whole thing better
> before posting potentially time-wasting newbie questions.

That's extremely considerate. Thanks !

(That said, in the process of "understanding the whole thing better", be sure to ask again, with a separate Subject, if you feel blocked on a sub-problem).

-Alex
0 new messages