Getting started with a service (LazDaemon) lazarus / 34-Windows ---------------------------------------------------------------------- TyneBridges · 2013-03-16 15:19 I've created a number of working programs with Borland Delphi 1, 2 and 5 (and still use Delphi at work) so am familiar with most of the basic conventions. However, I'm mystified when it comes to service apps. I've had a stab at a service that should simply write numbers to a text file using an fptimer, but I'm frustrated to find that I can't test it. From http://wiki.freepascal.org/Daemons_and_Services: When the daemon is started the command line parameters are parsed. The following are predefined: -i --install: register the daemon. This has no effect under unix. -u --uninstall: unregister the daemon. This has no effect under unix. -r --run: start the daemon. Windows does this normally itself. This implies that all I need to do after compiling my program is to type -i - in my case, bdaemon - i. I compiled it successfully, opened the folder and could see bdaemon.exe there. I right-clicked Windows Command Processor on my menu and selected "Run as administrator" and typed bdaemon -i. No error: good. I realise that this won't start the service, and that I need to do this manually, or by restarting Windows. However, when I go into Computer | Manage | Services and Applications | Services, surely I should then see bdaemon (or Bdaemon) in the alphabetical list? It's not there and I have no idea why. Down at the first hurdle... I can't find an example of how to use Lazdaemon with a step-by-step description of the requirements for Windows services. The Wiki is "bare bones" to say the least, and lumps Windows together with Unix. I'm completely unable to translate the following into what I need to do in my code. TDaemonMapper This component handles the service registration. Each instance needs one entry in the property DaemonDefs. My project does contain the following standard code, added automatically by Lazarus: Code: [Select]type   TDaemonMapper1 = class(TDaemonMapper)   private     { private declarations }   public     { public declarations }   end; var   DaemonMapper1: TDaemonMapper1; implementation procedure RegisterMapper; begin   RegisterDaemonMapper(TDaemonMapper1) end; {$R *.lfm} initialization   RegisterMapper; end.                           I'm fairly sure I've missed a property but have no idea what to add, or where. I would be grateful if anyone is able to tell me what I've done wrong, or point me to an example of how to use LazDaemon with Windows. ---------------------------------------------------------------------- BigChimp · 2013-03-16 15:27 FYI, for easier reading, use the # button in the editor bar to mark your code. This allows copy/pasting as well as formatting. Have no experience with writing services with fpc, sorry, so no advice there. ---------------------------------------------------------------------- TyneBridges · 2013-03-16 17:46 Thanks for the hint, BigChimp. I found the following article which looked useful http://www.turbog.com/wp-content/uploads/2012/04/daemons.pdf ...unfortunately this concentrates on FreePascal alone rather than Lazarus. Most of the code for the visual version is missing and I can't fill in the gaps. I've discovered DaemonMapper1 in the Lazarus default application via the Object Inspector. I changed DaemonDefs from 0 items to 1 item and allowed Lazarus to fill in the default name DaemonMapper1 (I haven't changed any of the other component or object default names). This does compile and now, when I issue the command bdaemon -i the result is Code: [Select]exception at 0040FCFF: Unknown daemon class name: . Hopefully someone has an example somewhere with Lazarus code, or can give me some hints on what I've missed. Translating the description of the mapper in the article above into Pascal code in the right places is beyond my knowledge. Any help would be gratefully received. ---------------------------------------------------------------------- TyneBridges · 2013-03-16 20:02 Following the create example for FP in the article, I've tried adding the following in mapunit and still get the error "Unknown daemon class name: ." when I try to install. For some reason, my daemon class name is not being picked up (incidentally, I tried D.DaemonClassName both with and without the initial T, recompiling after each edit). Code: [Select]procedure TDaemonMapper1.DaemonMapper1Create(Sender: TObject); Var D: TDaemonDef; begin      D:= DaemonDefs.Add as TDaemonDef;      D.DisplayName:= 'Booking Service';      D.Name:= 'BookingService';      D.DaemonClassName:= 'TDaemonMapper1';      D.WinBindings.ServiceType:= stWin32; end;  The article began this bit of code with "inherited Create(AOwner)". I tried inserting this but modifying it to inherited Create(Sender); Of course, that doesn't compile as Sender is the wrong object type. ---------------------------------------------------------------------- TyneBridges · 2013-03-17 11:18 I've now removed the code above and, by clicking into things I didn't even realise had click options, have managed to edit the properties for TDaemonMapper1 in the Object Inspector. I have 1 item in DaemonDefs called DaemonMapper1. Clicking on the line "1 item" gives me Editing DaemonMapper1.DaemonDefs[0] - evidently a zero-based array. In the Properties list I've added the same properties as in my code quoted, leaving UserName blank, which the help file says will run the service under the System account - as I want. I've recompiled the service but now, typing bdaemon -i at the Windows command prompt from the folder with the .exe file in it gives me Code: [Select]exception at 0040FCFF: Unknown daemon class name: TDaemonMapper1. Evidently something is still missing, but what? ---------------------------------------------------------------------- BigChimp · 2013-03-17 11:22 Attaching the project or uploading it somewhere would probably make it easiers for other to have a look and see what's wrong... ---------------------------------------------------------------------- BigChimp · 2013-03-17 18:19 No idea if this is relevant to you: http://bugs.freepascal.org/view.php?id=24067 Thanks, BigChimp ---------------------------------------------------------------------- TyneBridges · 2013-03-17 18:39 Thanks everyone for trying to help. I have finally managed to get my daemon to run. It looks as if it was my own silly mistake and that I had entered the daemon mapper name in the properties where I should have entered the daemon name. Seems I'm still groping my way along with a lot of trial and error. Latest problem: It seems fptimer doesn't work in a daemon (Windows service) because, although the timer is implemented using threads, I have been calling it from the main thread of my daemon, which (by design of Windows/FreePascal) has no message queue. Is there any simple way of ensuring the timer runs, i.e. without trying to write a threaded application - which I think is beyond my capabilities? (I suspect the answer is no, but it may be worth asking.) ---------------------------------------------------------------------- mdalacu · 2013-05-31 13:42 Does anyone know how to cleanly stop a thread started by demon? If i call FThread.Terminate from TDaemon1.DataModuleStop, the thread never gets a chance to finish. The app just exits. ---------------------------------------------------------------------- ChrisF · 2013-06-02 16:33 There has been a few other topics about daemons/services for windows recently. The second link is probably closer to your question: - http://www.lazarus.freepascal.org/index.php/topic,20308.0.html - http://www.lazarus.freepascal.org/index.php/topic,20652 Here is a modification of my daemon test code for the second topic (see attached file). I've just added an indication when the main thread task is ended (inside the TTestThread.Execute procedure): 'Application.Log(etcustom,'End of Thread');' I can clearly see this entry in my windows log. BTW, you may also have a look at this bug report, if your using 'standard' thread inside a 'standard' daemon project:  http://bugs.freepascal.org/view.php?id=24320 ---------------------------------------------------------------------- mdalacu · 2013-06-03 06:55 Hi ChrisF. Thank you for taking time to reply. I have tried everything  with no success. I have modified your attached example and still the thread does not close cleanly. Code: [Select]procedure TTestThread.Execute; var   logFile: TextFile; begin  AssignFile(logFile,'d:\Programare\Lazarus\NoWifiNetBridge\log.txt');  Rewrite(logFile);  while not Terminated  do     begin       Append(logFile);       sleep(1000);       Writeln(logFile,DateTimeToStr(Now));       Writeln(logFile,Terminated);       CloseFile(logFile);     end;  Append(logFile);  Writeln(logFile,'#Clean Shutdown.');  CloseFile(logFile); end;    This is the only part of the code that i have modified. The "Clean Shutdown" part never gets into the log. What am i doing wrong. Thank you very much. ---------------------------------------------------------------------- ChrisF · 2013-06-03 13:05 If we are using the same code, I guess something might be different in the way we use the service. Attached , the same sample with a bit of 'code-cleanup' and a log to a external file instead of the windows log; please, modify the path and name for this file according to your own needs: see "CLOG_FILENAME" in the "CallWriteLn" procedure. Here is my own results with this sample: Code: [Select]14:24:39: Daemon Install: -1 14:24:46: Daemon Start: -1 14:24:46: Daemon Execute: 0 14:24:46: Beginning of thread 14:24:47: Tick : 1 14:24:48: Tick : 2 ... 14:25:03: Tick : 17 14:25:04: Tick : 18 14:25:05: Daemon Stop: -1 14:25:05: Tick : 19 14:25:05: End of thread 14:25:19: Daemon UnInstall: -1 Obviously, the 'End of thread' entry is present. I've even tried with a longer sleep inside the thread (10 s instead of 1 s); just in case the thread might be canceled directly by windows when the service is stopped. Still no problems: the 'End of thread' entry is logged when the next timer tick occurs. Here is how I'm made my own tests, in order you can see if there is a difference with yours: 1/ Install the service: - type in console: daemon -i 2/ Start the service: -'start' menu inside the windows services manager for the corresponding service (called 'Test daemon') 3/ Stop the service (this could be different for you ?): -'stop' menu inside the windows services manager for the corresponding service 4/ Uninstall the service: - type in console: daemon -u I've also applied the FPC patch concerning the 100% CPU usage, but I don't think it could explain the difference. A final possibility is that there could be a something relative to the windows version: 'cause I'm still using windows XP for my tests. ---------------------------------------------------------------------- mdalacu · 2013-06-04 06:33 Hi ChrisF. Again, thank you for taking time with me. I think you are right regarding windows version. I am using Win8 All the steps are done in the same way/order like you. This is the log file: Code: [Select]9:29:37: Daemon Start: -1 9:29:37: Beginning of thread 9:29:37: Daemon Execute: 0 9:29:38: Tick : 1 9:29:39: Tick : 2 9:29:40: Tick : 3 9:29:41: Tick : 4 9:29:42: Tick : 5 9:29:43: Tick : 6 9:29:44: Tick : 7 9:29:45: Daemon Stop: -1 What else can i do? ---------------------------------------------------------------------- ChrisF · 2013-06-04 10:20 I don't have any direct access to a windows 8 computer, but I know someone else who can make some tests with it for me. I'll let you know about the results; so, we'll see if windows 8 is responsible of your troubles or not. You can still make another test, if you wish. Attached, another simple test program, but this time using a thread directly managed through windows API calls; not using the TThread class any more. This new test program is pretty close to the former one concerning the daemon/service part, but all the thread part has been replaced. I've not included the thread part into the TTestDaemon class, but anyway it's just to make some basic tests. The results are similar to what I've already got with my former tests: what about you ? Code: [Select]11:53:08: Daemon Install: -1 11:53:51: Daemon Start: -1 11:53:51: Start Timer Thread 11:53:51: Daemon Execute: 0 11:53:51: Beginning of thread 11:53:52: Tick : 1 11:53:53: Tick : 2 ... 11:54:04: Tick : 13 11:54:05: Tick : 14 11:54:05: Daemon Stop: -1 11:54:05: Stop Timer Thread 11:54:05: End of thread 11:54:26: Daemon UnInstall: -1 ---------------------------------------------------------------------- mdalacu · 2013-06-04 13:16 Hi, i have tested this and it works. Code: [Select]16:11:58: Daemon Start: -1 16:11:58: Start Timer Thread 16:11:58: Beginning of thread 16:11:58: Daemon Execute: 0 16:11:59: Tick : 1 16:12:00: Tick : 2 16:12:01: Tick : 3 16:12:02: Tick : 4 16:12:03: Daemon Stop: -1 16:12:03: Stop Timer Thread 16:12:03: End of thread If you need me to make same more test in order for you to patch  daemonapp, please do not hesitate. Thank you again. ---------------------------------------------------------------------- ChrisF · 2013-06-04 16:35 IMHO, there is nothing to patch. According to all your tests, it seems now that Windows 8 kills all the remaining active threads when a service stops, while Windows XP doesn't. So, you should end your service only when your thread has really ended. The simplest way would be to wait a little bit (i.e. sleep(a_given_time_in_ms)), but it's not recommended inside the start/stop procedures of a windows service. The best way is to use a event for that. As I've recently discovered in another topic of this forum that there is an object for events within FPC, here is how to modified my former sample code (you could also use the Windows API directly, though it's of course less portable). Attached, a modified version of my sample 3, using only TCustomDaemon, TThread and RTLEvent  (no more any windows API calls). Here is my results: Code: [Select]18:14:14: Daemon Install: -1 18:14:35: Daemon Start: -1 18:14:35: Daemon Execute: 0 18:14:35: Beginning of thread 18:14:36: Tick : 1 18:14:37: Tick : 2 ... 18:14:45: Tick : 10 18:14:46: Daemon Stop: -1 18:14:46: Calling Thread End 18:14:46: Waiting for Thread End... 18:14:46: Tick : 11 18:14:46: End of thread 18:14:46: Thread End Got  ->  Exit 18:15:08: Daemon UnInstall: -1 It should also work for you too (well, at least theoretically). If it does, just be sure to call the 'RTLEventSetEvent' function at the very end of your main thread procedure/function (i.e. it should always be the last line of code for this procedure). ---------------------------------------------------------------------- mdalacu · 2013-06-05 09:31 Thank you very much. It works! I will adapt my program with this solution. ---------------------------------------------------------------------- mdalacu · 2013-06-07 10:11 A unrelated question: Can i write to system log from the working thread? It always crashes, but if i write from a daemon method it works. Code: [Select]procedure TWorkingThread.Execute; begin ... Daemon1.EventLog1.Info('Tick.');  <-- Crashes!!! end; procedure TDaemon1.DataModuleStart(Sender: TCustomDaemon; var OK: Boolean); begin ...   EventLog1.LogType:=ltSystem;   EventLog1.Active:=True;   EventLog1.RegisterMessageFile('');   EventLog1.Resume;   EventLog1.Log('Service Started!');  <-- It works just fine! end; How can i modify my code to make it work? Thank you. ---------------------------------------------------------------------- ChrisF · 2013-06-07 17:49 Honestly, 'till there "Application.Log" has been quite enough for me (for a sample to how to use it, see daemon2.zip in this topic). Otherwise, you can try to put your EventLog object into your daemon class. This event may then be reached inside the thread code, via the Parent property of the thread. See attached sample (i.e. "daemon3-withEventLog.zip). It's possible that it's not working for more recent versions of windows; but it does for me... **Edit **: I've wrongly used EventLog.Log instead of EventLog.Info inside the thread code in my sample; but, after retesting, both of them are working anyway. ---------------------------------------------------------------------- mdalacu · 2013-06-08 18:18 Thank you ChrisF very much for your answer. As soon as i will be able to test this i will post back results. I have written 3 multi threaded apps by now and the "parent" thing still eludes me ...  As a side note, i have observed that EvenLog does not write to sistem log on windows (only file log) in builds newer than 1.0.8 (the one included with Code Typhoon 4.20 and 4.30). ---------------------------------------------------------------------- ChrisF · 2013-06-10 01:11 Of course, there are not any 'parent' notions if you consider only the threads themselves. It's just that within the sample coming from Lazarus/FPC, the TThread object has been encapsulated into the TDaemon object. But, it's not mandatory. To comply the object rules, and to stick to the sample conception, I've also used object code in my former samples. But once again, you don't HAVE to. So, in my samples, I've added a parent property into my own inherited Thread class (affected with the SetParent method), just to be able to reach easily the TDaemon (i.e. the 'parent') properties/methods directly into the thread code. That's all. Concerning your last remark, do you mean "Lazarus" 1.0.8 ? Which sounds a bit strange to me, because  I guess EventLog is most probably a part of FPC, not of Lazarus. Unless Code Typhoon is also using a newer version of FPC (I know there are still a few bug issues with the next-to-come FPC 2.7.1. release). ---------------------------------------------------------------------- mdalacu · 2013-06-10 06:08 Of course, your code works perfectly! Thank you again ChrisF. My program was exactly like yours except the line where i was calling the logger: Code: [Select]Daemon1.EventLog1.Info('Tick.');  By change it into Parent.EventLog1.Info('Tick.');   , everything works. So, i still does not understand the differences...Demon1 is the parent of my TWorkingThread, but if i call it this way it crashes.  For the second issue, yes i was referring to the shipped with CT 4.30. And yes it is using a newer fpc 2.7.1, but if i use eventlog.pp from 1.0.8 then it works in CT 4.30, so i don't think it is related with fpc 2.7.1. All i have to do now is to get rid of the "ugly text" inserted into the System Log (http://bugs.freepascal.org/view.php?id=24390), which i still don't figure how to do it. ---------------------------------------------------------------------- ChrisF · 2013-06-10 12:23 I've also noticed that the messages in the windows system log are not correctly formatted. According to the infos posted into the bug issue you've reported, and after a few tests, adding the 'fclel.res' file did the trick for me. Attached, a modified version of my last sample with this solution. You must use only the EvenLog.Warning, .Error, .Debug and .Info methods to obtain valid and formated messages (and not use the EventLog.Log method, which is undefined into the fclel.res file). Just for test purposes, I've used all the 4 possibilities into this last sample, as you can see. Note: the messages are correctly formatted, but only if the concerned service is installed. If not, you'll still get unformatted message displays. It's not necessary that the service is running; but it must be installed (to let windows access to the concerned formatting infos). Another possibility seems to build your own message format file, and to register it with the EventLog.RegisterMessageFile method; I've not tried it, but according to the bug issue, it's also working. ---------------------------------------------------------------------- mdalacu · 2013-06-11 05:43 Thank you, it works. Now all my previous log entries are correctly formatted!    This forum needs a achievements system or a thank you button for posts like yours! ---------------------------------------------------------------------- mdalacu · 2015-12-11 10:02 I have another BIG problem.... I have started to create a daemon which has a main thread, windows platform. This main thread spanws other work threads. This work threads has OnTerminate  property filled with a procedure from the main thread. The problem is that these work threads, when they terminate, never calls this HandleTerminatedThreads procedure. The problem is that demon applications do not have an event loop? What can i do....help Thank you. ---------------------------------------------------------------------- mglazuser · 2016-11-30 19:49 Same issue #25. Thread.OnTerminate is not working, the assigned procedure is never been called after Thread.Terminate. Any suggestions to this problem? Thx in advance. ---------------------------------------------------------------------- mglazuser · 2016-12-01 14:14 In my opininon its a bug of FPC with the title "Thread destructor not called in daemons". That refers to Windows 7 The Event OnTerminate(@ThreadStopped) will never be called, its useless to implement it, you can check this also in the example of ChrisF #15 above. .. procedure TTestDaemon.ThreadStopped(Sender: TObject); // never been called! begin   FreeAndNil(FThread); //USELESS :-( end; .. As a workaround you have to handle the problem manually and call the destructor of your thread by yourself as ChrisF suggested in #22 with a Event. Or you use FreeOnTerminate=True like here http://www.gocher.me/Daemon ---------------------------------------------------------------------- ngx234 · 2022-01-10 05:37 This one -> OK Only one bug, mem leak when stop the service Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i { Lazarus servie, Windows 10 64.  Lazarus 2.2.0 (rev lazarus_2_2_0-7-gb938b1d561)  FPC 3.2.3 i386-win32-win32/win64 Windows: cmd line administrator:  install service  : LazarusService.exe -i                   : sc create "LazarusService" binpath="C:\L\_src\DaemonService\Service\LazarusService.exe"  start service    : sc start LazarusService  stop service     : sc stop LazarusService --> mem leak  uninstall service: sc delete LazarusService  check status     : sc queryex LazarusService https://f orum.lazarus.freepascal.org/index.php/topic,57754.0.html, thanks getmem } program LazarusService; {$mode objfpc}{$H+} uses  HeapTrc,{$IFDEF UNIX}{$IFDEF UseCThreads}  CThreads,{$ENDIF} Cmem,{$ENDIF}  sysutils, classes, daemonapp, {jwawindows, } eventlog; type   { TWorkerThread }  TWorkerThread = class(TThread)  private    FIsPaused: Boolean;  protected    procedure Execute; override;  public    destructor Destroy; override;  end;   TDaemon = class(TCustomDaemon)  private    FWorkerThread: TWorkerThread;    procedure DoTerminate(Sender: TObject);  public    function ShutDown: Boolean; override;    function Stop: Boolean; override;    function Start: Boolean; override;    function Pause: Boolean; override;    function Continue: Boolean; override;  end;   TDaemonMapper = class(TCustomDaemonMapper)  private  public    constructor Create(AOwner: TComponent); override;  end; procedure TWorkerThread.Execute;const ii : int64 = 0;begin  Application.Log(etDebug, 'WorkerThreadExecute: entering Execute event');  try    while not Terminated do begin      try        Sleep(5000);        if (not FIsPaused) then begin          //do something        end;        Application.Log(etDebug, ii.ToString);      inc(ii);      except        on e:Exception do begin          Application.Log(etDebug, e.Message);        end;//on e      end;//except    end;//while  finally    Application.Log(etDebug, 'WorkerThreadExecute: leaving Execute event ---- .');    OnTerminate(Self);  end;end;//procedure TWorkerThread.Execute; destructor TWorkerThread.Destroy;begin  Application.Log(etDebug, 'WorkerThreadDestroy');  inherited Destroy;end; procedure TDaemon.DoTerminate(Sender: TObject);begin  Application.Log(etDebug, 'DaemonDoTerminate: Worker thread terminated!!!!!');  if FWorkerThread <> nil then    FreeAndNil(FWorkerThread);end; function TDaemon.Start: Boolean;begin  Result := inherited Start;  Application.Log(etDebug, 'DaemonStart: LazarusService started.');  FWorkerThread := TWorkerThread.Create(True);  FWorkerThread.FIsPaused := False;  FWorkerThread.OnTerminate := @DoTerminate;  FWorkerThread.FreeOnTerminate := False;  FWorkerThread.Start;end; function TDaemon.Stop: Boolean;var ii : Int64 = 0;begin  FWorkerThread.Terminate;  while(FWorkerThread<>nil)do begin    Sleep(500);    Application.Log(etDebug, 'DaemonStop: Waiting for workerThread '+ii.ToString);    inc(ii);  end;  Result := inherited Stop;  Application.Log(etDebug, 'DaemonStop: LazarusService stopped.');end; function TDaemon.Pause: Boolean;begin  Result := inherited Pause;  FWorkerThread.FIsPaused := True;  Application.Log(etDebug, 'DaemonPause: LazarusService paused.');end; function TDaemon.Continue: Boolean;begin  Result := inherited Continue;  FWorkerThread.FIsPaused := False;  Application.Log(etDebug, 'DaemonContinue: LazarusService resumed.');end; function TDaemon.ShutDown: Boolean;begin  Result := inherited ShutDown;  Application.Log(etDebug, 'DaemonShutdown: LazarusService shutdown.');end; constructor TDaemonMapper.Create(AOwner: TComponent);var MyDaemonDef: TDaemonDef;begin  inherited Create(AOwner);  Application.Log(etDebug, 'DaemonCreate: LazarusService successfully created.');  MyDaemonDef := DaemonDefs.Add as TDaemonDef;  MyDaemonDef.DaemonClassName := TDaemon.ClassName;  MyDaemonDef.Name := 'LazarusService';  MyDaemonDef.DisplayName := 'LazarusService display name';  MyDaemonDef.Description := 'Description Break session 0 isolation';  MyDaemonDef.LogStatusReport := False;  with MyDaemonDef.WinBindings do begin    ServiceType := stWin32;    StartType := stAuto; //stBoot //stManual    ErrorSeverity := esNormal;    WaitHint := 0;    IDTag := 0;  end;end;//constructor TDaemonMapper.Create(AOwner: TComponent); begin//main program LazarusService;  RegisterDaemonClass(TDaemon);  RegisterDaemonMapper(TDaemonMapper);  heaptrc.SetHeapTraceOutput(ChangeFileExt(ParamStr(0), '.heaptrc.txt'));  with Application do begin    Title := 'LazarusServiceApplication';    EventLog.LogType := ltFile;    EventLog.DefaultEventType := etDebug;    EventLog.AppendContent := true;    //EventLog.FileName := ExtractFilePath(Application.ExeName) + '.log';    EventLog.FileName := ChangeFileExt(ParamStr(0), '.log');  Initialize;    Run;  end;end.//file C:\L\_src\DaemonService\Service>LazarusService.exe -i C:\L\_src\DaemonService\Service>dir  Volume in drive C is ssd111  Volume Serial Number is F4F2-65F4  Directory of C:\L\_src\DaemonService\Service 01/10/2022  12:22              . 01/10/2022  12:22              .. 01/10/2022  12:15              backup 01/10/2022  11:46           263,680 LazarusService.exe 01/10/2022  12:22               327 LazarusService.heaptrc.txt 01/10/2022  12:22                99 LazarusService.log 01/10/2022  11:46             1,973 LazarusService.lpi 01/10/2022  12:15            10,702 LazarusService.lpr 01/07/2022  16:04            23,277 LazarusService.lpr.html 01/10/2022  11:46            10,457 LazarusService.lps 01/07/2022  16:51            17,935 LazarusService__OK.lpr 01/10/2022  11:27              lib                8 File(s)        328,450 bytes                4 Dir(s)  75,417,079,808 bytes free C:\L\_src\DaemonService\Service>type LazarusService.log LazarusService [2022-01-10 12:22:21.310 Debug] DaemonCreate: LazarusService successfully created. C:\L\_src\DaemonService\Service>type LazarusService.heaptrc.txt C:\L\_src\DaemonService\Service\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\_src\DaemonService\Service\LazarusService.exe 171 memory blocks allocated : 5941/6368 171 memory blocks freed     : 5941/6368 0 unfreed memory blocks : 0 True heap size : 262144 (128 used in System startup) True free heap : 262016 C:\L\_src\DaemonService\Service>sc queryex lazarusService SERVICE_NAME: lazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 1  STOPPED         WIN32_EXIT_CODE    : 1077  (0x435)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 0         FLAGS              : C:\L\_src\DaemonService\Service>sc start lazarusService SERVICE_NAME: lazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 2  START_PENDING                                 (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 9852         FLAGS              : C:\L\_src\DaemonService\Service>type LazarusService.log LazarusService [2022-01-10 12:22:21.310 Debug] DaemonCreate: LazarusService successfully created. LazarusService [2022-01-10 12:23:10.956 Debug] DaemonCreate: LazarusService successfully created. LazarusService [2022-01-10 12:23:10.958 Debug] DaemonStart: LazarusService started. LazarusService [2022-01-10 12:23:10.958 Debug] WorkerThreadExecute: entering Execute event LazarusService [2022-01-10 12:23:15.960 Debug] 0 LazarusService [2022-01-10 12:23:20.966 Debug] 1 C:\L\_src\DaemonService\Service>type LazarusService.heaptrc.txt C:\L\_src\DaemonService\Service\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\_src\DaemonService\Service\LazarusService.exe 171 memory blocks allocated : 5941/6368 171 memory blocks freed     : 5941/6368 0 unfreed memory blocks : 0 True heap size : 262144 (128 used in System startup) True free heap : 262016 C:\L\_src\DaemonService\Service>sc stop lazarusService SERVICE_NAME: lazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 3  STOP_PENDING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0 C:\L\_src\DaemonService\Service>sc queryex lazarusService SERVICE_NAME: lazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 1  STOPPED         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 0         FLAGS              : C:\L\_src\DaemonService\Service>type LazarusService.log LazarusService [2022-01-10 12:22:21.310 Debug] DaemonCreate: LazarusService successfully created. --> LazarusService.exe -i LazarusService [2022-01-10 12:23:10.956 Debug] DaemonCreate: LazarusService successfully created. --> sc start lazarusService (why twice?) LazarusService [2022-01-10 12:23:10.958 Debug] DaemonStart: LazarusService started. LazarusService [2022-01-10 12:23:10.958 Debug] WorkerThreadExecute: entering Execute event LazarusService [2022-01-10 12:23:15.960 Debug] 0 LazarusService [2022-01-10 12:23:20.966 Debug] 1 LazarusService [2022-01-10 12:23:25.981 Debug] 2 LazarusService [2022-01-10 12:23:30.995 Debug] 3 LazarusService [2022-01-10 12:23:36.008 Debug] 4 LazarusService [2022-01-10 12:23:41.019 Debug] 5 LazarusService [2022-01-10 12:23:46.024 Debug] 6 LazarusService [2022-01-10 12:23:48.315 Debug] DaemonStop: Waiting for workerThread 0 LazarusService [2022-01-10 12:23:48.829 Debug] DaemonStop: Waiting for workerThread 1 LazarusService [2022-01-10 12:23:49.343 Debug] DaemonStop: Waiting for workerThread 2 LazarusService [2022-01-10 12:23:49.844 Debug] DaemonStop: Waiting for workerThread 3 LazarusService [2022-01-10 12:23:50.357 Debug] DaemonStop: Waiting for workerThread 4 LazarusService [2022-01-10 12:23:50.858 Debug] DaemonStop: Waiting for workerThread 5 LazarusService [2022-01-10 12:23:51.031 Debug] 7 LazarusService [2022-01-10 12:23:51.031 Debug] WorkerThreadExecute: leaving Execute event ---- . LazarusService [2022-01-10 12:23:51.031 Debug] DaemonDoTerminate: Worker thread terminated!!!!! LazarusService [2022-01-10 12:23:51.031 Debug] WorkerThreadDestroy LazarusService [2022-01-10 12:23:51.373 Debug] DaemonStop: Waiting for workerThread 6 LazarusService [2022-01-10 12:23:51.373 Debug] DaemonStop: LazarusService stopped. C:\L\_src\DaemonService\Service>type LazarusService.heaptrc.txt C:\L\_src\DaemonService\Service\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\_src\DaemonService\Service\LazarusService.exe 171 memory blocks allocated : 5941/6368 171 memory blocks freed     : 5941/6368 0 unfreed memory blocks : 0 True heap size : 262144 (128 used in System startup) True free heap : 262016 C:\L\_src\DaemonService\Service\LazarusService.exe --run Heap dump by heaptrc unit of C:\L\_src\DaemonService\Service\LazarusService.exe 320 memory blocks allocated : 12509/13576 319 memory blocks freed     : 12457/13520 1 unfreed memory blocks : 52                            -->> sc stop -> mem leak True heap size : 262144 (128 used in System startup) True free heap : 262016 Should be : 261864 Call trace for block $01564B38 size 52   $00401BB1   $0042E821   $0040330F   $75F5FA29   $779C7A9E   $779C7A6E   $0042E821   $0040330F   $75F5FA29   $779C7A9E   $779C7A6E C:\L\_src\DaemonService\Service>sc delete LazarusService [SC] DeleteService SUCCESS C:\L\_src\DaemonService\Service> ---------------------------------------------------------------------- balazsszekely · 2022-01-10 07:51 @ngx234 QuoteOnly one bug, mem leak when stop the serviceHope you are not a spammer. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TDaemon.Stop: Boolean;var ii : Int64 = 0;begin  FWorkerThread.Terminate;  FWorkerThread.WaitFor; //<--add this  FWorkerThread.Free;//<--add this  while(FWorkerThread<>nil)do begin  Sleep(500);    Application.Log(etDebug, 'DaemonStop: Waiting for workerThread '+ii.ToString);    inc(ii);  end;  Result := inherited Stop;  Application.Log(etDebug, 'DaemonStop: LazarusService stopped.');end; ---------------------------------------------------------------------- ngx234 · 2022-01-10 09:53 @getmem, no more memory leak, but the service can not be stopped. Always in STATE=3 STOP_PENDING Tried on Win10 x64, Win7 x86, win7 x64 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TDaemon.Stop: Boolean;var ii : Int64 = 0;begin  FWorkerThread.Terminate;  Application.Log(etDebug, 'DaemonStop: After terminate');  FWorkerThread.WaitFor;  Application.Log(etDebug, 'DaemonStop: After waitfor');  //doesn't come here ......  FWorkerThread.Free;  Application.Log(etDebug, 'DaemonStop: After free');  while(FWorkerThread<>nil)do begin    Sleep(500);    Application.Log(etDebug, 'DaemonStop: Waiting for workerThread '+ii.ToString);    inc(ii);  end;  Result := inherited Stop;  Application.Log(etDebug, 'DaemonStop: LazarusService stopped.');end; C:\L\w7x64>LazarusService.exe -i C:\L\w7x64>type LazarusService.heaptrc.txt C:\L\w7x64\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\w7x64\LazarusService.exe 171 memory blocks allocated : 5566/6008 171 memory blocks freed     : 5566/6008 0 unfreed memory blocks : 0 True heap size : 229376 (112 used in System startup) True free heap : 229264 C:\L\w7x64>type LazarusService.log LazarusService [2022-01-10 16:46:55.284 Debug] DaemonCreate: LazarusService successfully created. C:\L\w7x64>sc start LazarusService SERVICE_NAME: LazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 2  START_PENDING                                 (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x7d0         PID                : 2420         FLAGS              : C:\L\w7x64>sc queryex LazarusService SERVICE_NAME: LazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 4  RUNNING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 2420         FLAGS              : C:\L\w7x64>type LazarusService.log LazarusService [2022-01-10 16:46:55.284 Debug] DaemonCreate: LazarusService successfully created. LazarusService [2022-01-10 16:47:41.866 Debug] DaemonCreate: LazarusService successfully created. LazarusService [2022-01-10 16:47:41.866 Debug] DaemonStart: LazarusService started. LazarusService [2022-01-10 16:47:41.881 Debug] WorkerThreadExecute: entering Execute event LazarusService [2022-01-10 16:47:46.889 Debug] 0 LazarusService [2022-01-10 16:47:51.897 Debug] 1 LazarusService [2022-01-10 16:47:56.904 Debug] 2 C:\L\w7x64>type LazarusService.heaptrc.txt C:\L\w7x64\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\w7x64\LazarusService.exe 171 memory blocks allocated : 5566/6008 171 memory blocks freed     : 5566/6008 0 unfreed memory blocks : 0 True heap size : 229376 (112 used in System startup) True free heap : 229264 C:\L\w7x64>sc stop LazarusService SERVICE_NAME: LazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 3  STOP_PENDING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0 C:\L\w7x64>type LazarusService.heaptrc.txt C:\L\w7x64\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\w7x64\LazarusService.exe 171 memory blocks allocated : 5566/6008 171 memory blocks freed     : 5566/6008 0 unfreed memory blocks : 0 True heap size : 229376 (112 used in System startup) True free heap : 229264 C:\L\w7x64>type LazarusService.log LazarusService [2022-01-10 16:46:55.284 Debug] DaemonCreate: LazarusService successfully created. LazarusService [2022-01-10 16:47:41.866 Debug] DaemonCreate: LazarusService successfully created. LazarusService [2022-01-10 16:47:41.866 Debug] DaemonStart: LazarusService started. LazarusService [2022-01-10 16:47:41.881 Debug] WorkerThreadExecute: entering Execute event LazarusService [2022-01-10 16:47:46.889 Debug] 0 LazarusService [2022-01-10 16:47:51.897 Debug] 1 LazarusService [2022-01-10 16:47:56.904 Debug] 2 LazarusService [2022-01-10 16:48:01.912 Debug] 3 LazarusService [2022-01-10 16:48:06.919 Debug] 4 LazarusService [2022-01-10 16:48:11.927 Debug] 5 LazarusService [2022-01-10 16:48:16.935 Debug] 6 LazarusService [2022-01-10 16:48:21.942 Debug] 7 LazarusService [2022-01-10 16:48:22.831 Debug] DaemonStop: After terminate LazarusService [2022-01-10 16:48:26.950 Debug] 8 LazarusService [2022-01-10 16:48:26.950 Debug] WorkerThreadExecute: leaving Execute event ---- . LazarusService [2022-01-10 16:48:26.950 Debug] DaemonDoTerminate: Worker thread terminated!!!!! LazarusService [2022-01-10 16:48:26.950 Debug] WorkerThreadDestroy C:\L\w7x64>sc queryex LazarusService SERVICE_NAME: LazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 3  STOP_PENDING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 2420         FLAGS              : C:\L\w7x64>sc queryex LazarusService SERVICE_NAME: LazarusService         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 3  STOP_PENDING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 2420         FLAGS              : C:\L\w7x64>sc stop LazarusService [SC] ControlService FAILED 1061: The service cannot accept control messages at this time. C:\L\w7x64> ---------------------------------------------------------------------- balazsszekely · 2022-01-10 11:31 @ngx234 Quotebut the service can not be stopped. Always in STATE=3 STOP_PENDINGTest the attached project from the following post: https:/ /forum.lazarus.freepascal.org/index.php/topic,57754.msg429768.html#msg 429768 ---------------------------------------------------------------------- ngx234 · 2022-01-10 16:26 @getmem Quote from: GetMem on January 10, 2022, 12:31:32 pm@ngx234 Quotebut the service can not be stopped. Always in STATE=3 STOP_PENDINGTest the attached project from the following post: https:/ /forum.lazarus.freepascal.org/index.php/topic,57754.msg429768.html#msg 429768 program on post #27, base on your Service.zip.  Same result ---------------------------------------------------------------------- balazsszekely · 2022-01-12 05:01 @ngx234 Quoteprogram on post #27, base on your Service.zip.  Same resultJust tested, it does stop at my side. ---------------------------------------------------------------------- ngx234 · 2022-01-12 07:34 @getmem I didn't make myself clear in reply #27 Yes it is working. Only one glitch: when stop LazarusService, it will stop, but there is 1 memory leak (tWorkerThread). Quote from: GetMem on January 12, 2022, 06:01:27 am@ngx234 Quoteprogram on post #27, base on your Service.zip.  Same resultJust tested, it does stop at my side. C:\L\_src\DaemonService\Service>type LazarusService.log LazarusService [2022-01-10 12:22:21.310 Debug] DaemonCreate: LazarusService successfully created. --> LazarusService.exe -i LazarusService [2022-01-10 12:23:10.956 Debug] DaemonCreate: LazarusService successfully created. --> sc start lazarusService (why twice?) ---------------------------------------------------------------------- balazsszekely · 2022-01-14 06:00 @ngx234 Here is the log on my side: QuoteD:\Service>_install.bat D:\Service>LazarusService.exe -i D:\Service>sc start lazarusservice SERVICE_NAME: lazarusservice         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 2  START_PENDING                                 (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 11268         FLAGS              : D:\Service>type log.txt LazarusService [2022-01-14 07:46:29.878 Debug] Service successfully created. LazarusService [2022-01-14 07:47:24.696 Debug] Service successfully created. LazarusService [2022-01-14 07:47:24.697 Debug] Service started. LazarusService [2022-01-14 07:47:24.698 Debug] Entering worker thread Execute event D:\Service>type heaptrace.log D:\Service\LazarusService.exe -i Heap dump by heaptrc unit of D:\Service\LazarusService.exe 168 memory blocks allocated : 6242/6696 168 memory blocks freed     : 6242/6696 0 unfreed memory blocks : 0 True heap size : 491520 (112 used in System startup) True free heap : 491408 D:\Service>sc queryex lazarusservice SERVICE_NAME: lazarusservice         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 4  RUNNING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0         PID                : 11268         FLAGS              : D:\Service>sc stop lazarusservice SERVICE_NAME: lazarusservice         TYPE               : 10  WIN32_OWN_PROCESS         STATE              : 3  STOP_PENDING                                 (STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)         WIN32_EXIT_CODE    : 0  (0x0)         SERVICE_EXIT_CODE  : 0  (0x0)         CHECKPOINT         : 0x0         WAIT_HINT          : 0x0 D:\Service>type log.txt LazarusService [2022-01-14 07:46:29.878 Debug] Service successfully created. LazarusService [2022-01-14 07:47:24.696 Debug] Service successfully created. LazarusService [2022-01-14 07:47:24.697 Debug] Service started. LazarusService [2022-01-14 07:47:24.698 Debug] Entering worker thread Execute event LazarusService [2022-01-14 07:50:08.783 Debug] Leaving worker thread Execute event. LazarusService [2022-01-14 07:50:08.783 Debug] Woker thread terminated. LazarusService [2022-01-14 07:50:09.288 Debug] Service stopped. D:\Service>type heaptrace.log D:\Service\LazarusService.exe -i Heap dump by heaptrc unit of D:\Service\LazarusService.exe 168 memory blocks allocated : 6242/6696 168 memory blocks freed     : 6242/6696 0 unfreed memory blocks : 0 True heap size : 491520 (112 used in System startup) True free heap : 491408 D:\Service> As you can see: "0 unfreed memory blocks : 0", so no leaks. Are you sure you tested the attached service from the link? PS: I just noticed that in your log is also "0 unfreed memory blocks : 0". You are not leaking,  everything is OK. ---------------------------------------------------------------------- ngx234 · 2022-01-14 08:51 hi Getmem I test again your service.zip. Just add, use heaptrc unit in project option. And add 1 line : heaptrc.SetHeapTraceOutput(ChangeFileExt(ParamStr(0), '.heaptrc.txt')); I can stop the service, but 52 bytes mem leak  C:\L\_src\DaemonService\ServiceGetmemOriginal>type LazarusService.heaptrc.txt C:\L\_src\DaemonService\ServiceGetmemOriginal\LazarusService.exe -i Heap dump by heaptrc unit of C:\L\_src\DaemonService\ServiceGetmemOriginal\LazarusService.exe 172 memory blocks allocated : 7153/7616 172 memory blocks freed     : 7153/7616 0 unfreed memory blocks : 0 True heap size : 524288 (144 used in System startup) True free heap : 524144 C:\L\_src\DaemonService\ServiceGetmemOriginal\LazarusService.exe --run Heap dump by heaptrc unit of C:\L\_src\DaemonService\ServiceGetmemOriginal\LazarusService.exe 218 memory blocks allocated : 8527/9168 217 memory blocks freed     : 8475/9112 1 unfreed memory blocks : 52 True heap size : 524288 (144 used in System startup) True free heap : 524144 Should be : 523992 Call trace for block $06B500D8 size 52   $00401B61   $00431FC1 Few seconds after :  sc stop lazarusservice Please check ->    : sc query lazarusservice Or please attach your last source code, I will compile and test it  Win 10 x64, My IDE: Lazarus 2.2.0 (rev lazarus_2_2_0-10-g991a5bbf25) FPC 3.2.3 i386-win32-win32/win64 Lazarus 2.2.0 (rev lazarus_2_2_0-10-g991a5bbf25) FPC 3.3.1 i386-win32-win32/win64 ---------------------------------------------------------------------- balazsszekely · 2022-01-14 10:01 I attached the source. Still no memory leak at my side. I'm working with Lazarus Trunk/FPC 3.2.2. ---------------------------------------------------------------------- ngx234 · 2022-01-15 04:48 Quote from: GetMem on January 14, 2022, 11:01:30 amI attached the source. Still no memory leak at my side. I'm working with Lazarus Trunk/FPC 3.2.2. Thanks getmem, there is no mem leak in your example. The culprit is in my code Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var ss : string;begin//main program LazarusService;  RegisterDaemonClass(TDaemon);  RegisterDaemonMapper(TDaemonMapper);   //SetHeapTraceOutput(ChangeFileExt(ParamStr(0),'.txt')); //mem leak on stop service!!!   //ss:=ParamStr(0)+'.txt'; SetHeapTraceOutput(ss);      //also mem leak on stop service!!!   ss:=ParamStr(0)+'.txt';                                //no mem leak   SetHeapTraceOutput('heaptrc.txt');                       //no mem leak   GlobalSkipIfNoLeaks:=True;   Application.Title := 'Lazarus Service Application title';  Application.EventLog.LogType := ltFile;  Application.EventLog.DefaultEventType := etDebug;  Application.EventLog.AppendContent := true;  //Application.EventLog.FileName := ExtractFilePath(Application.ExeName) + '.log';  Application.EventLog.FileName := ChangeFileExt(ParamStr(0), '.log');  //no mem leak  Application.Initialize;  Application.Run;end.//file {test.bat==================begindel      *.txt     *.logpause    sc delete lazarusServicesc delete lazarusServicepause    lazarusService.exe -ilazarusService.exe -isc queryex lazarusServicepause    sc start lazarusServicesc start lazarusServicesc queryex lazarusServicepause    sc stop lazarusServicesc stop lazarusServicepause    sc queryex lazarusServicesc queryex lazarusServicepause    sc delete lazarusServicesc delete lazarusServicetype   *.txt   *.logtest.bat==================end}