-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsimpleipcwrapper.pas
More file actions
executable file
·116 lines (95 loc) · 2.67 KB
/
simpleipcwrapper.pas
File metadata and controls
executable file
·116 lines (95 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
unit SimpleIPCWrapper;
// SimpleIPC has a flaw under unix (bug 17248).
// Use this workaround since there's no way to extend SimpleIPC classes directly (bug 19136)
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, SimpleIPC;
procedure InitServer(Server: TSimpleIPCServer);
function IsServerRunning(Client: TSimpleIPCClient): Boolean;
implementation
{$ifdef unix}
uses
BaseUnix;
const
//F_RDLCK = 0;
F_WRLCK = 1;
//F_UNLCK = 2;
function GetPipeFileName(Server: TSimpleIPCServer): String;
begin
Result := Server.ServerID;
if not Server.Global then
Result := Result + '-' + IntToStr(fpGetPID);
Result := '/tmp/' + Result;
end;
function GetPipeFileName(Client: TSimpleIPCClient): String;
begin
Result := Client.ServerID;
if Client.ServerInstance <> '' then
Result := Result + '-' + Client.ServerInstance;
Result := '/tmp/' + Result;
end;
function SetLock(FileDescriptor: cint): Boolean;
var
LockInfo: FLock;
begin
LockInfo.l_type := F_WRLCK;
LockInfo.l_whence := SEEK_SET;
LockInfo.l_len := 0;
LockInfo.l_start := 0;
Result := FpFcntl(FileDescriptor, F_SetLk, LockInfo) <> -1;
end;
procedure InitServer(Server: TSimpleIPCServer);
var
PipeFileName: String;
PipeDescriptor: cint;
begin
Server.StartServer;
PipeFileName := GetPipeFileName(Server);
PipeDescriptor := FpOpen(PipeFileName, O_RDWR, $1B6);
if PipeDescriptor <> -1 then
begin
//Pipe file created. Try to set the lock
if not SetLock(PipeDescriptor) then
begin
FpClose(PipeDescriptor);
raise Exception.CreateFmt('UniqueInstance - A server instance of %s is already running', [Server.ServerID]);
end;
end
else
raise Exception.CreateFmt('UniqueInstance - Error creating pipe file for server %s', [Server.ServerID]);
end;
function IsServerRunning(Client: TSimpleIPCClient): Boolean;
var
PipeFileName: String;
PipeDescriptor: cint;
begin
//check the pipe file
PipeFileName := GetPipeFileName(Client);
PipeDescriptor := FpOpen(PipeFileName, O_RDWR, $1B6);
Result := PipeDescriptor <> -1;
if Result then
begin
// pipe file exists
// try to set the lock
// if lock is created then is a stale file (server process crashed or killed)
Result := not SetLock(PipeDescriptor);
FpClose(PipeDescriptor);
if not Result then
begin
//delete stale file
FpUnlink(PipeFileName);
end;
end;
end;
{$else}
procedure InitServer(Server: TSimpleIPCServer);
begin
Server.StartServer;
end;
function IsServerRunning(Client: TSimpleIPCClient): Boolean;
begin
Result := Client.ServerRunning;
end;
{$endif}
end.