Recent

Author Topic: Comunication between running processes  (Read 4521 times)

simone

  • Hero Member
  • *****
  • Posts: 573
Comunication between running processes
« on: July 22, 2018, 08:43:26 pm »
Hello everyone. I have to create two programs that communicate between them during execution. The first program starts the second. The two processes, while they are running, exchange information in a bidirectional way and both perform operations that depend on the information exchanged. I'm considering TProcess and SimpleIPC, but I have no previous experience in this context. Does anyone have any suggestions? Thanks in advance.
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Comunication between running processes
« Reply #1 on: July 22, 2018, 09:58:45 pm »
Both TProcess and SimpleIPC are straightforward. Just try it, then ask in case of trouble.
However note, it seems like SimpleIPC implemented with asynchronous queue model, so it is unidirectional.
Thus you will need a pair client+server per process for bidirectional communication, or consider use of tcp (http?) server for synchronous communications. There's no much to suggest without knowing your actual requirements.
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Comunication between running processes
« Reply #2 on: July 22, 2018, 11:31:01 pm »
I am aware that I have expressed my requirements at a very high level of abstraction. I can add that the two processes run in the same machine. I will do some experiment with TProcess.
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Comunication between running processes
« Reply #3 on: July 26, 2018, 05:34:45 pm »

I did some experiments with SimpleIPC, writing a client and a server with the following code. The two programs behave as I expect, but the main form of the server freezes after starting. Is it possible to avoid this problem? I have attached the complete code for convenience. Thank you very much.

Code: Pascal  [Select][+][-]
  1. unit Unit1; //CLIENT
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, simpleipc, FileUtil, Forms, Controls, Graphics, Dialogs,
  9.   StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     SendButton: TButton;
  17.     ConnectButton: TButton;
  18.     Edit1: TEdit;
  19.     SimpleIPCClient1: TSimpleIPCClient;
  20.     procedure SendButtonClick(Sender: TObject);
  21.     procedure ConnectButtonClick(Sender: TObject);
  22.   private
  23.  
  24.   public
  25.  
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.SendButtonClick(Sender: TObject);
  38. begin
  39.   SimpleIPCClient1.SendStringMessage(Edit1.Text);
  40.   Edit1.Text:='';
  41. end;
  42.  
  43. procedure TForm1.ConnectButtonClick(Sender: TObject);
  44. begin
  45.   if SimpleIPCClient1.ServerRunning then
  46.     begin
  47.       SimpleIPCClient1.Connect;
  48.       Caption:='CLIENT CONNECTED';
  49.     end;
  50. end;
  51.  
  52. end.




Code: Pascal  [Select][+][-]
  1. unit unit2; //SERVER
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, simpleipc, FileUtil, Forms, Controls, Graphics, Dialogs,
  9.   StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     ButtonStart: TButton;
  17.     ButtonStop: TButton;
  18.     Memo: TMemo;
  19.     SimpleIPCServer1: TSimpleIPCServer;
  20.     procedure ButtonStartClick(Sender: TObject);
  21.     procedure ButtonStopClick(Sender: TObject);
  22.   private
  23.     Running : boolean;
  24.   public
  25.  
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.ButtonStartClick(Sender: TObject);
  38. var
  39.   Msg : string;
  40. begin
  41.   SimpleIPCServer1.Active:=True;
  42.   Running:=True;
  43.   Caption:='SERVER ON';
  44.   repeat
  45.     Application.ProcessMessages;
  46.     if SimpleIPCServer1.PeekMessage(10,True) then
  47.       begin
  48.         SimpleIPCServer1.ReadMessage;
  49.         Msg:=SimpleIPCServer1.StringMessage;
  50.         Memo.Lines.Add(Msg);
  51.       end;
  52.   until Msg='stop';
  53. end;
  54.  
  55. procedure TForm1.ButtonStopClick(Sender: TObject);
  56. begin
  57.   SimpleIPCServer1.StopServer;
  58.   Running:=False;
  59.   Caption:='SERVER OFF';
  60. end;
  61.  
  62. end.
  63.  
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Comunication between running processes
« Reply #4 on: July 26, 2018, 10:42:58 pm »
Don't use loops, just start server threaded (probably a use of CThreads will be required) and OnMessageQueued.

See attached example.
« Last Edit: July 26, 2018, 10:45:02 pm by sash »
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Comunication between running processes
« Reply #5 on: July 26, 2018, 11:43:50 pm »
Thank you. Unfortunately, under Windows, even in your example, after the server shutdown with AServer.StopServer, the application hangs...
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Comunication between running processes
« Reply #6 on: July 27, 2018, 12:52:41 am »
hello,
Thank you. Unfortunately, under Windows, even in your example, after the server shutdown with AServer.StopServer, the application hangs...
because you aren't in a console application you can try to start the server not in the threaded mode  :
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender : TObject);
  2. begin
  3.   if AServer.Active then
  4.     begin
  5.     AClient.Disconnect;
  6.     AServer.StopServer;
  7.     end
  8.  
  9.   else
  10.     AServer.StartServer(false);
  11.   MemoLog.Append('Server state:' + BoolToStr(AServer.Active, 'on', 'off'));
  12. end;

click on the attachment to see animation.

Friendly, J.P


« Last Edit: July 27, 2018, 01:02:52 am by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Comunication between running processes
« Reply #7 on: July 27, 2018, 01:17:27 am »
Thank you. Unfortunately, under Windows, even in your example, after the server shutdown with AServer.StopServer, the application hangs...

I'm going to offer a method which I know how to do with pure Windows API but have no idea whatsoever how it's done with the LCL.

A very simple way to implement what you've described is for the parent process to create two named mapped files.  In one of the mapped files, the parent process writes information that is read by the child process.  The other mapped file is where the child process writes information meant for the parent process to read.  The nice thing about this method is that there is no need for threads to block or wait for events/mutexes/etc because each mapped file has only one writer and one reader. 

Synchronization is implemented simply by having a counter (usually at the beginning of the mapped file) which is read by the reader and incremented by the writer.  If the counter has been incremented since the last time it was read then there is new information, if the counter hasn't changed, the process can do something else before checking the counter again later.

A fancier implementation has 2 separate threads (one in each process) checking the counters and, if there is no change, go to sleep for a few milliseconds before checking again (or do some other work).

Depending on exactly what your processes do, there is probably a variation of this method that can be fitted to the needs of your program.  Another plus of this method is that the parent and child process can write a message to their mapped file letting the other know that it is alive and when it is ending/terminating along with its exit code.   This is basically a "ping" whereby each process writes a message every tenth of second (if it doesn't have information to post) letting the other know it is alive.  That saves you from having to write code to find out if either process is dead/hung/terminated/mummified/embalmed/etc.

I hope that may be helpful to you.  If I knew how to do that using the LCL, I'd gladly offer some code but, you don't want LCL code from me (at least not at this time.)


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Comunication between running processes
« Reply #8 on: July 27, 2018, 01:03:36 pm »
Yes, I tested under Wine, even in non-threaded mode there are freeze problems (at client side) with reconnect, but normally, you don't need to shutdown server in the middle of work, so this could be solved by notifying clients about server shutdown.

@440bx : For Windows-only communication there's much easier method, like FindWindow + SendMessage.

@simone, what's your exact scheme of apps interaction? I also suggested tcp/http server for bidirectional communication.

Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Comunication between running processes
« Reply #9 on: July 27, 2018, 03:38:58 pm »
Eliminating the multithread I solved the problem of freezing the server. I have two processes: the first performs a task and must notify after each step the second process, which performs a monitoring function. Thanks for your help.
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Comunication between running processes
« Reply #10 on: July 27, 2018, 03:56:13 pm »
@440bx : For Windows-only communication there's much easier method, like FindWindow + SendMessage.
For very small amounts of data that works fine and it can also be used for simple synchronization in many cases. 
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018