Hi everyone!
I'm trying to create a daemon/service. I'm following this link
https://wiki.freepascal.org/Daemons_and_Services#Daemons_have_no_Access_to_Network-_and_Cloud_Drives_.28Onedrive.2C_Dropbox.29.
First I went the OnlyCode way, I just copy-pasted the code and I ran into:
function TDaemon1.Install: boolean;
var
FilePath: string;
begin
Result := False;
{$IFDEF WINDOWS}
Result := inherited Install;
{$ELSE}
{$IFDEF UNIX}
FilePath := GetSystemdControlFilePath(Self.Definition.Name);
LogToFile(Format('TDaemon1: installing control file: %s',[FilePath]));
Result := CreateSystemdControlFile(self, FilePath); // <----------------------- I'm getting an error here
if not Result then
LogToFile('TDaemon1: Error creating systemd control file: ' + FilePath);
{$ENDIF}
{$ENDIF}
LogToFile(Format('TDaemon1: service %s installed: %s', [self.Definition.Name, BoolToStr(Result, 'ok', 'failure')]));
end;
I get:
kdaemon.lpr(145,46) Error: Incompatible type for arg no. 1: Got "TDaemon1", expected "TDaemon"
I commented it out and I managed to run the daemon. As expected, running my app with -i failed (as it's commented out), -u was OK and -r ran as needed, I checked the given PID and it was really running.
The I took the other approach. I created a new project "Daemon (service) application". First I played with OnStart / OnStop events, adding some simple Writeln, I ran it and it worked, fired with -r gave expected output and the same when I killed the process.
But then I kept following the tutorial and added the DataModuleStart and DataModuleStops procedures, this resulted in:
kdaemonunit.pas(43,3) Error: Identifier not found "FDaemonWorkerThread"
and indeed, the tutorial doesn't mention any
var, whatsoever so I peeked on the OnlyCode version and added some
uses and declared
FDaemonWorkerThreadIt compiles but when I run it, I get
$ ./KDaemon -i
An unhandled exception occurred at $00000000004284F4:
EDaemon: Not changing daemon mapper class TKDaemonMapper with TTestDaemonMapper: Only 1 mapper allowed.
$00000000004284F4
$00000000004283D7
$00000000004F2999 DAEMONMAPPERUNIT_$$_init$, line 40 of daemonmapperunit.pas
$00000000004174AC
I get the same either I use any parameter or not.
Complete code:
unit KDaemonUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, DaemonApp, lazdaemonapp, daemonmapperunit, DaemonUnit,
DaemonWorkerThread;
type
{ TKDaemon }
TKDaemon = class(TDaemon)
procedure DataModuleStart(Sender: TCustomDaemon; var OK: Boolean);
procedure DataModuleStop(Sender: TCustomDaemon; var OK: Boolean);
private
FDaemonWorkerThread: TDaemonWorkerThread;
public
end;
var
KDaemon: TKDaemon;
implementation
procedure RegisterDaemon;
begin
RegisterDaemonClass(TKDaemon)
end;
{$R *.lfm}
{ TKDaemon }
procedure TKDaemon.DataModuleStart(Sender: TCustomDaemon; var OK: Boolean);
begin
Writeln(Format('Daemon received start signal, PID:%d', [GetProcessID]));
// Create a suspended worker thread - see DaemonWorkerThread unit
FDaemonWorkerThread := TDaemonWorkerThread.Create;
// Parametrize it
FDaemonWorkerThread.FreeOnTerminate := False;
// Start the worker
FDaemonWorkerThread.Start;
OK := True;
end;
procedure TKDaemon.DataModuleStop(Sender: TCustomDaemon; var OK: Boolean);
begin
Writeln('Daemon received stop signal');
// stop and terminate the worker
if assigned(FDaemonWorkerThread) then
begin
FDaemonWorkerThread.Terminate;
// Wait for the thread to terminate.
FDaemonWorkerThread.WaitFor;
FreeAndNil(FDaemonWorkerThread);
end;
Writeln('Daemon stopped');
OK := True;
end;
initialization
RegisterDaemon;
end.
At this point I have absolutely no clue what I did wrong. Any hint?