Recent

Author Topic: Getting started with a service (LazDaemon)  (Read 33090 times)

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Getting started with a service (LazDaemon)
« Reply #15 on: June 04, 2013, 06:35:00 pm »

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

  • Full Member
  • ***
  • Posts: 202
    • dmSimpleApps
Re: Getting started with a service (LazDaemon)
« Reply #16 on: June 05, 2013, 11:31:57 am »
Thank you very much. It works! I will adapt my program with this solution.
 :D

mdalacu

  • Full Member
  • ***
  • Posts: 202
    • dmSimpleApps
Re: Getting started with a service (LazDaemon)
« Reply #17 on: June 07, 2013, 12:11:27 pm »
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

  • Hero Member
  • *****
  • Posts: 542
Re: Getting started with a service (LazDaemon)
« Reply #18 on: June 07, 2013, 07:49:40 pm »
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.
« Last Edit: June 07, 2013, 07:55:25 pm by ChrisF »

mdalacu

  • Full Member
  • ***
  • Posts: 202
    • dmSimpleApps
Re: Getting started with a service (LazDaemon)
« Reply #19 on: June 08, 2013, 08:18:19 pm »
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 ...  :o
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

  • Hero Member
  • *****
  • Posts: 542
Re: Getting started with a service (LazDaemon)
« Reply #20 on: June 10, 2013, 03:11:09 am »
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

  • Full Member
  • ***
  • Posts: 202
    • dmSimpleApps
Re: Getting started with a service (LazDaemon)
« Reply #21 on: June 10, 2013, 08:08:07 am »
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.  :o

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

  • Hero Member
  • *****
  • Posts: 542
Re: Getting started with a service (LazDaemon)
« Reply #22 on: June 10, 2013, 02:23:36 pm »
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

  • Full Member
  • ***
  • Posts: 202
    • dmSimpleApps
Re: Getting started with a service (LazDaemon)
« Reply #23 on: June 11, 2013, 07:43:44 am »
Thank you, it works. Now all my previous log entries are correctly formatted!  :o  :D
This forum needs a achievements system or a thank you button for posts like yours!

mdalacu

  • Full Member
  • ***
  • Posts: 202
    • dmSimpleApps
Re: Getting started with a service (LazDaemon)
« Reply #24 on: December 11, 2015, 11:02:24 am »
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

  • Newbie
  • Posts: 2
Re: Getting started with a service (LazDaemon)
« Reply #25 on: November 30, 2016, 08:49:53 pm »
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.
« Last Edit: December 01, 2016, 04:45:50 pm by mglazuser »

mglazuser

  • Newbie
  • Posts: 2
Re: Getting started with a service (LazDaemon)
« Reply #26 on: December 01, 2016, 03:14:43 pm »
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
« Last Edit: December 02, 2016, 03:25:32 pm by mglazuser »