[fpc-pascal] Inter-process communication, a cautionary tale
Mark Morgan Lloyd
markMLl.fpc-pascal at telemetry.co.uk
Wed Jul 18 17:01:16 CEST 2012
OBones wrote:
> Mark Morgan Lloyd wrote:
>> A couple of weeks ago, out of curiosity rather than necessity, I
>> started looking at whether the library could be ported to Windows
>> using MS-style named pipes. However I seem to have hit a snag since it
>> appears that Windows can't both create a named pipe (for reading) and
>> open the same named pipe (for writing) in the same process, something
>> that gives unix sockets no problems at all.
> Could you show us some code here?
> And what return values do you get?
> I'm asking because I have distinct memories of doing just that a while
> back without any issue.
I've certainly done it to communicate between separate processes, but
the difference in the current case is that the first time the program is
loaded I'm enqueueing its own parameters rather than passing them via an
in-memory "shortcut"... works fine in unix and seemed like a good idea
at the time :-) It's strange though just how many people on
StackOverflow etc. say things like "using a named pipe to communicate
inside a single process is utterly pointless", it's almost as though
they're parroting some doctrine the origin of which is now lost.
Basically, what I was trying to do was this. In the main thread:
fIpcPipe:= CreateNamedPipe(PChar(fIpcName), PIPE_ACCESS_INBOUND,
PIPE_TYPE_MESSAGE + PIPE_READMODE_MESSAGE,
1, 0, 0, 1000, NIL (* @sa *) );
That works. Fire up a background reader thread, and make sure that the
main thread doesn't proceed...
fThread:= TSphinxThread.Create(false);
while fThread.fSyncParam = DEADBEEF DO (* Until thread has called
ConnectNamedPipe() *)
Sleep(10);
fThread.Suspend
..until after the Execute in the reader thread has done:
fSyncParam := ''; (* Let main process see that
we've started *)
{$ifndef UNIX }
IF NOT ConnectNamedPipe(Phix.Pipe, NIL) THEN
EXIT;
{$endif UNIX }
WHILE NOT Terminated DO BEGIN
I'm keenly aware of the deprecated status of calling Suspend from
outside the thread, but what I'm showing there is just one attempt from
many.
Finally, once the main thread is confident that the background reader
has got to the point of being connected to the named pipe:
sendPipe:= CreateFile(PChar(fIpcName), GENERIC_WRITE,
FILE_SHARE_WRITE + FILE_SHARE_READ,
NIL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
IF sendPipe = INVALID_HANDLE_VALUE THEN BEGIN
fSlaveInitErrorNum:= GetLastError; (* 230: bad pipe. 231: pipe
busy. *)
That invariably fails with an error 231, at which point after quite a
lot of tinkering and comparison against my older code I gave up.
--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk
[Opinions above are the author's, not those of his employers or colleagues]
More information about the fpc-pascal
mailing list