Bo Berglund wrote:
On Sat, 31 Oct 2015 10:22:08 +0000, Mark Morgan Lloyd
<[email protected]> wrote:
Bo Berglund wrote:
What does the main thread do? If you can contrive to write that as a
loop, then as you've already been told you can call CheckSynchronize()
which hands control to whatever's been queued by threads using
Synchronize().
Right now the main thread (you mean the program code itself in the
console program DoRun event, right) does this (mostly debug messages
into the console):
I don't use Indy, but If I'm reading that lot correctly the answer is
"outputs a couple of messages and terminates, within a second of startup".
Everybody's usage of threads etc. differs, depending on what they're
doing and what their background is, so I hope somebody else is checking
what I'm saying here (there's a big difference between using something
and being competent to explain it- I consider myself in the former
category). What I'd do is change the main code to be a loop to output
your test messages without starting a background thread, and to loop for
say a minute with Sleep() and CheckSynchronize(): if this crashes then
you've got bigger problems.
Once this runs enable your comms thread and get it to output a couple of
messages via Synchronize(), again this should not crash while the main
program is running.
After that concentrate on- in particular- shutting down in good order,
i.e. making sure that background threads are terminated before pulling
the process out from under them.
Writeln('Freeing FComm at time ' + IntToStr(T2-T1));
finally
FComm.Free;
end;
// stop program loop
Terminate;
end;
And the output into the console is this:
Creating TCP client
Start communications at time 27
Connecting to www.sunet.se on port 80
Going to sleep 500 at time 27
Event: Socket connected! Time = 71 ms
Waking up from sleep 500, at time 527
Going to sleep 300 at time 527
Waking up from sleep 300 at time 827
Terminating thread
Freeing FComm at time 827
I hope somebody else will comment about how much housekeeping FPC does
here, but I do believe you've got a race condition: what happens if the
main thread (i.e. the overall process) terminates faster than the
background thread?
When I run it in Lazarus there is a pop-up window saying:
Project IndyTCPtest raised exception class 'External: SIGSEGV'.
At address 3132
Make sure you're compiling with debugging enabled.
Depending on exactly what the program does, you might need to do
I just wanted to make a test with the TThread child I created, which
also contains the TIdTcpClient object, to see if the events fire off.
But I only get a single one into my code, then the SIGSEGV error.
You need to loop dequeuing events.
something like fudging keyboard access using fpSelect(), but basically
it works... I've got a mainframe emulator here which responds to
keyboard commands and also interleaves output from the various backend
processes, I've used Lazarus as the IDE but it's entirely a console app.
I will have to figure out a way to make the test code do that loop. I
had hoped that while executing sleep() statements the main thread
would yield to the TCP thread but it seems like it does not...
Definitely not. Think about it for a moment: Sleep() is basically a
low-level OS call, it really doesn't want to get involved with the
complexity of deciding whether it's already in an event handler or is in
a background thread.
A good starting point would be having the main loop run for a fixed
time- a minute or something like that. In my case I've fudged my own
keyboard handler etc. in a way that (hopefully) will allow me to use a
GUI frontend, in other words it has to either poll the keyboard (the
simpler case) or use fpSelect(). Potentially, for a non-GUI program
keyboard handling etc. could simply be moved into its own thread so when
it's accumulated a command (e.g. 'quit') it simply enqueues it using
Synchronize() and the main thread decides what to do with it.
I cannot use Synchronize because then the events fire off only when
the main program code ends and if I don't use Synchronize then I get a
SIGSEG exception somewhere.
Assume that none of the LCL is thread-safe, i.e. background threads have
no safe UI access. Assume that the RTL and FCL are not specifically
thread safe except where documented, but that you can use it in
conjunction with conventional "cautious" programming techniques.
I have assumed as much so there is no side access to any data as far
as I can tell.
Again, this is just a very simple console test program to check the
operations of the threaded TCPIP communications, nothing near the
final code because there I will have exit conditions and such.
Start off with a very simple program to /only/ test a background thread.
I'd suggest leaving Indy etc. out of it until you're confident that it
works and never throws an exception, /particularly/ during startup and
shutdown.
--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk
[Opinions above are the author's, not those of his employers or colleagues]
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus