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

Reply via email to