* Markus Elfring <
Markus....@web.de>
| > Now if (1) finishes very quickly (since we have next to no delay in the
| > data sender), we call finish on Thread 2 at (2) very quickly, too.
>
| The execution of the test data provider (as a child process) will take
| a moment. The procedure “finish” is called by the socket management thread
| only after this external command was executed by the main thread, isn't it?
Yes. But this only means that the external command has finished, not
that all the processing of the output of that command already has taken
place in the other threads. Especially with small one-liner output like
in my client.tcl, I expect lots of buffering in the TCP stack of the OS.
| > Thread 2 will handle this 'finish' request when it enters the event loop,
>
| It should wait on a corresponding termination condition after test
| data were received.
Well, "it should". Making it actually do so is the challenge in multi-threading :-)
| > Noe we have several events pending in Thread 2:
| > - two more incoming socket requests
| > - one thread::send call to "proc finish"
| > - one "after 0"-call to hand_over from the first socket request.
>
| My expectation was that the needed worker threads were created (in the meantime).
Verify that expectation by adding stderr output in the thread creation
code, right at the beginning and immediately before the end of procs.
You will see that this expectation is not always fulfilled.
| > (what is checked first: sockets? TCL thread events? plain 'after' events?).
| >
| > *If* finish is entered first (which it does on my computer),
>
| This is possible.
Ok...
| > thread 2 closes the server port
>
| I wonder about this information.
proc finish {} \
{
global context hcc hcm lso sc sm workers
=> close $lso
Here.
| > It does not handle the pending socket calls any more.
>
| I would find this detail unexpected.
| Should data from test TCP connections still be appropriately processed?
How? The incoming sockets are handled in thread 2, but thread 2 now is
blocked in 'finish' waiting for
while {[set lw [llength ${workers}]] != [set lf [tsv::get ${context} finished]]} \
As I said before, add debugging output to the start and end of the procs
to see the sequence (or in this case missing sequence) of events.
Here are test runs on my computer with various delays in client.tcl:
delay -1, delay 0 (i.e. as quick as possible on the client side)
% tclsh8.6 test-statistic-server8.tcl
1. run
waiting: 127.0.0.1 localhost 42918 ::1 localhost 42918
client.tcl STARTED localhost 42918
client.tcl Openend 3 connections: sock4 sock5 sock6
client.tcl Content sent to sock4 sock5 sock6
client.tcl Connections closed: sock4 sock5 sock6
client.tcl EXIT
tid0x7f6de7c5a700 finish cond wait
1 workers: tid0x7f6de6bb8700
0 finished
[blocks]
"delay 1" (i.e. wait a teeny weeny bit)
% tclsh8.6 test-statistic-server8.tcl
1. run
waiting: 127.0.0.1 localhost 41902 ::1 localhost 41902
client.tcl STARTED localhost 41902
client.tcl Openend 3 connections: sock4 sock5 sock6
client.tcl Content sent to sock4 sock5 sock6
tid0x7f735b7ae700 handle_connection cond wait
client.tcl Connections closed: sock4 sock5 sock6
client.tcl EXIT
tid0x7f735af5d700 handle_connection cond wait
tid0x7f7360b8d700 finish cond wait
3 workers: tid0x7f735b7ae700 tid0x7f735af5d700 tid0x7f735a70c700
0 finished
tid0x7f735b7ae700 handle_connection: cond notify
tid0x7f7360b8d700 finish cond wait
3 workers: tid0x7f735b7ae700 tid0x7f735af5d700 tid0x7f735a70c700
1 finished
tid0x7f735af5d700 handle_connection: cond notify
tid0x7f7360b8d700 finish cond wait
3 workers: tid0x7f735b7ae700 tid0x7f735af5d700 tid0x7f735a70c700
2 finished
[blocks]
"delay 10" (slooooow, give everyone time to do their job)
% tclsh8.6 test-statistic-server8.tcl
1. run
waiting: 127.0.0.1 localhost 42383 ::1 localhost 42383
client.tcl STARTED localhost 42383
client.tcl Openend 3 connections: sock4 sock5 sock6
client.tcl Content sent to sock4 sock5 sock6
tid0x7f01df00b700 handle_connection cond wait
tid0x7f01de7ba700 handle_connection cond wait
tid0x7f01ddf69700 handle_connection cond wait
client.tcl Connections closed: sock4 sock5 sock6
client.tcl EXIT
tid0x7f01e00ad700 finish cond wait
3 workers: tid0x7f01df00b700 tid0x7f01de7ba700 tid0x7f01ddf69700
0 finished
tid0x7f01de7ba700 handle_connection: cond notify
tid0x7f01e00ad700 finish cond wait
3 workers: tid0x7f01df00b700 tid0x7f01de7ba700 tid0x7f01ddf69700
1 finished
tid0x7f01ddf69700 handle_connection: cond notify
tid0x7f01e00ad700 finish cond wait
3 workers: tid0x7f01df00b700 tid0x7f01de7ba700 tid0x7f01ddf69700
2 finished
tid0x7f01df00b700 handle_connection: cond notify
2. run
waiting: 127.0.0.1 localhost 41083 ::1 localhost 41083
client.tcl STARTED localhost 41083
client.tcl Openend 3 connections: sock4 sock5 sock6
client.tcl Content sent to sock4 sock5 sock6
tid0x7f01e00ad700 handle_connection cond wait
tid0x7f01df00b700 handle_connection cond wait
tid0x7f01ddf69700 handle_connection cond wait
client.tcl Connections closed: sock4 sock5 sock6
client.tcl EXIT
tid0x7f01dd718700 finish cond wait
3 workers: tid0x7f01e00ad700 tid0x7f01df00b700 tid0x7f01ddf69700
0 finished
tid0x7f01e00ad700 handle_connection: cond notify
tid0x7f01dd718700 finish cond wait
3 workers: tid0x7f01e00ad700 tid0x7f01df00b700 tid0x7f01ddf69700
1 finished
tid0x7f01df00b700 handle_connection: cond notify
tid0x7f01dd718700 finish cond wait
3 workers: tid0x7f01e00ad700 tid0x7f01df00b700 tid0x7f01ddf69700
2 finished
tid0x7f01ddf69700 handle_connection: cond notify
3. run
waiting: 127.0.0.1 localhost 45478 ::1 localhost 45478
client.tcl STARTED localhost 45478
client.tcl Openend 3 connections: sock4 sock5 sock6
client.tcl Content sent to sock4 sock5 sock6
tid0x7f01dd718700 handle_connection cond wait
tid0x7f01ddf69700 handle_connection cond wait
tid0x7f01df00b700 handle_connection cond wait
client.tcl Connections closed: sock4 sock5 sock6
client.tcl EXIT
tid0x7f01de7ba700 finish cond wait
3 workers: tid0x7f01dd718700 tid0x7f01ddf69700 tid0x7f01df00b700
0 finished
tid0x7f01ddf69700 handle_connection: cond notify
tid0x7f01de7ba700 finish cond wait
3 workers: tid0x7f01dd718700 tid0x7f01ddf69700 tid0x7f01df00b700
1 finished
tid0x7f01df00b700 handle_connection: cond notify
tid0x7f01de7ba700 finish cond wait
3 workers: tid0x7f01dd718700 tid0x7f01ddf69700 tid0x7f01df00b700
2 finished
tid0x7f01dd718700 handle_connection: cond notify
incidence|"available records"|"return code"|"command output"
3|3|0|
Seems to work most of the times, but sometimes I also get
2|1|0|
1|1|0|
or similar, i.e. even the slow sender is not reliable, but I think this
is what your original question was about.
Fix the fast processing which now blocks, then the slow one should be
fixed, too.
<joke>
All of this will be much easier when TIP 131 is finally implemented.
https://core.tcl.tk/tips/doc/trunk/tip/131.md
Don't hold your breath, though...
</joke>
HTH
R'