Lazarus

Free Pascal => General => Topic started by: MarkMLl on April 17, 2019, 10:13:42 am

Title: Threads, handles and serial comms on Linux
Post by: MarkMLl on April 17, 2019, 10:13:42 am
I wonder if I could ask for some general advice. On Linux (and Solaris etc.) the standard serial unit is a thin wrapper around fpRead(), fpSelect() and so on. I was under the impression that file handles- in common with other resource ownership- were an attribute of the process, and as such could be shared across threads.

I'm doing some conversion work on a program originally written at the end of the last Millennium, where the user interface can be driven by GUI, an internal command line or internal scripting. I find myself having to do some fairly heroic rewiring, since things that worked using Delphi and Win-32 quite simply aren't portable.

The GUI thread is, among other things, opening a serial port using FPC's standard serial unit and holding onto the handle. It's getting a command from the user, for example to run a terminal emulator. The command is being run by a background thread to allow the GUI to remain responsive, with Synchronize() used where necessary.

What I appear to have is that if the background thread accesses the serial port (via the standard serial unit) directly using the handle obtained by the GUI thread then it can send data but not receive it: a laptop attached to the serial port sees anything it sends echoed back.

If the background thread accesses the serial port via Synchronize() then everything works as expected.

I've not yet tried giving the background thread a local copy of the serial ports handle.

I'd be very interested in anybody's comments on this.

This is superficially similar to a problem that Bo Berglund aired last September, but I believe he was using Windows and the serial.pp unit is completely different.

MarkMLl
Title: Re: Threads, handles and serial comms on Linux
Post by: MarkMLl on April 17, 2019, 02:45:56 pm
Testing continues but it looks as though using fpDup() to create a temporary handle works, i.e. something as simple as

procedure terminalEmulator(handle: TSerialHandle); // Running in background thread

begin
  handle := fpDup(handle);
  try
...
  finally
    fpClose(handle)
  end
end;

If anybody could throw any light on this I'd be very interested in their comments.

MarkMLl
Title: Re: Threads, handles and serial comms on Linux
Post by: marcov on April 17, 2019, 03:01:53 pm
Maybe something drains the serial in onidle or so. Do you use lazserial, or do you really do everything manual with unit serial?
Title: Re: Threads, handles and serial comms on Linux
Post by: MarkMLl on April 17, 2019, 06:01:11 pm
Everything direct to serial.pp Something's changed: I ripped out yesterday evening's code that had got things working by forcing serial read/write to the GUI thread and added an fpDup() (i.e. so that the background thread had its own handle) which worked, then I reverted to the original situation where the background thread was using the GUI thread's handle and it still worked.

So there's something odd going on. I'm fairly certain it's not in my code, there's no significant LCL or FPC code "in circuit", and I'm reluctant to blame the Linux kernel's thread handling. It could be that there's some per-port state and that it will recur the next time the system's rebooted, but by now I'm waiting for it.

Heisenbugs: don't you just love 'em? :-)

MarkMLl
Title: Re: Threads, handles and serial comms on Linux
Post by: dsiders on April 17, 2019, 06:24:00 pm
Heisenbugs :-)

That's one I've never seen/heard before. I'm going to borrow it...
Title: Re: Threads, handles and serial comms on Linux
Post by: 440bx on April 17, 2019, 06:27:39 pm
That's one I've never seen/heard before. I'm going to borrow it...
They'll go well with "Murphybugs".
Title: Re: Threads, handles and serial comms on Linux
Post by: Thaddy on April 17, 2019, 06:33:31 pm
dsiders is probably right.
https://en.wikipedia.org/wiki/Heisenbug

The other option is of course a mebug.
TinyPortal © 2005-2018