You are not logged in.
OS: CentOS v5.11 x64
CodeTyphon: v5.10 multiArch
Typhon: x86
Console application code:
program project1;
{$mode delphi}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF}
Classes, SysUtils, CustApp,
// BaseUnix, SynCommons;
BaseUnix;
type
TMyApplication = class(TCustomApplication)
protected
procedure DoRun; override;
end;
procedure TMyApplication.DoRun;
begin
Sleep(3000);
WriteLn('DoRun');
// stop program loop
// Terminate;
end;
Procedure DoSig(sig : cint);cdecl;
begin
writeln('Receiving signal: ',sig);
end;
var
// http://www.freepascal.org/docs-html/rtl/oldlinux/sigaction.html
oa,na: PSigActionRec;
Application: TMyApplication;
begin
new(na);
new(oa);
na^.sa_Handler:=SigActionHandler(@DoSig);
fillchar(na^.Sa_Mask,sizeof(na^.sa_mask),#0);
na^.Sa_Flags:=0;
{$ifdef Linux} // Linux specific
na^.Sa_Restorer:=Nil;
{$endif}
if fpSigAction(SIGINT,na,oa)<>0 then
// if fpSigAction(SIGTERM,na,oa)<>0 then
begin
writeln('Error: ',fpgeterrno,'.');
halt(1);
end;
Application:=TMyApplication.Create(nil);
Application.StopOnException:=True;
Application.Title:='My Application';
Application.Run;
Application.Free;
Writeln ('Exit now...');
end.
When SynCommons is not used, the application can react to SIGINT (Ctrl+C), as shown below:
[xli@localhost _Delphi_Proj_]$ ./project1
DoRun
Receiving signal: 2
Receiving signal: 2
Receiving signal: 2
DoRun
DoRun
However, when SynCommons is used, the application can NOT react to SIGINT (Ctrl+C), as shown below:
[xli@localhost _Delphi_Proj_]$ ./project1
DoRun
DoRun
DoRun
Could you help to comment on the reason and the possible workaround ? Many thanks !
Offline
First, try to include Synopse.inc into your program, to see if the FPC settings inside have influence.
Please report back.
Offline
Thank you for your kind help. The same problem applies for the following code:
program project1;
{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER
uses
{$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF}
Classes, SysUtils, CustApp,
BaseUnix, SynCommons;
// BaseUnix;
type
TMyApplication = class(TCustomApplication)
protected
procedure DoRun; override;
end;
procedure TMyApplication.DoRun;
begin
Sleep(3000);
WriteLn('DoRun');
// stop program loop
// Terminate;
end;
Procedure DoSig(sig : cint);cdecl;
begin
writeln('Receiving signal: ',sig);
end;
var
// http://www.freepascal.org/docs-html/rtl/oldlinux/sigaction.html
oa,na: PSigActionRec;
Application: TMyApplication;
begin
new(na);
new(oa);
na^.sa_Handler:=SigActionHandler(@DoSig);
fillchar(na^.Sa_Mask,sizeof(na^.sa_mask),#0);
na^.Sa_Flags:=0;
{$ifdef Linux} // Linux specific
na^.Sa_Restorer:=Nil;
{$endif}
if fpSigAction(SIGINT,na,oa)<>0 then
// if fpSigAction(SIGTERM,na,oa)<>0 then
begin
writeln('Error: ',fpgeterrno,'.');
halt(1);
end;
Application:=TMyApplication.Create(nil);
Application.StopOnException:=True;
Application.Title:='My Application';
Application.Run;
Application.Free;
Writeln ('Exit now...');
end.
Offline
Sorry ... my mistake .. this is (not yet) what I meant !
I meant: include Synopse.inc without including SynCommons, just to check the influence of the settings inside Synopse.inc on your program.
Offline
Thank you for your time and comments !
With Synopse.inc and without SynCommons, the console app can respond to SIGINT.
Offline
AFAIK there is no explicit SIGINT removal in our code.
I found this:
http://forum.lazarus.freepascal.org/ind … ic=13335.0
Sounds like if once FPC's crt unit is linked to the application:
- SIGINT is caught but do not end the process;
- use manual Ctrl+C keypress track.
Online
Wow ! Thank you very much for your help in identifying the problem !...
Offline
Thanks Ab !
In addition to the OP.
Would it be something to consider: a switch (define) to include or exclude the whole of testing (and the crt unit, that is only needed for cosmetics during testing).
In production, SynCommons without testing framework would be ok (and leaner).
Offline
... or we may try to create new SynLog.pas and SynTest.pas units so that SynCommons.pas would be smaller...
I'm not sure if we may be able to do this easily, but I would try.
Online
If you can spare the time ... this would be a nice and welcome change !
Offline
I have introduced the new SynLog.pas and SynTests.pas units, extracted from SynCommons.
And fixed the dependency to crt.pp, so that under FPC the SIGINT message would still apply as usual.
See http://synopse.info/fossil/info/881797779c
Online
Excellent excellent news ! Thank you very much for your great work !
Offline
In case it might be useful, the following link contains an working example of signal trapping for Kylix (not just Ctrl+C).
http://homepage3.nifty.com/isayan/kxsigroute.html
// http://homepage3.nifty.com/isayan/kylixTips.html
// http://homepage3.nifty.com/isayan/kxsigroute.html
program Kylix_Signal;
{$APPTYPE CONSOLE}
uses
LibC, SysUtils;
procedure SignalSet(func:TSignalHandler);
var
smask: TSigset;
act: TSigAction;
begin
(* Signal mask setting *)
sigemptyset(smask);
sigaddset(smask,SIGINT);
sigaddset(smask,SIGTERM);
act.__sigaction_handler := func;
act.sa_mask := smask;
act.sa_flags := 0;
(* Signal exit function registered *)
sigaction(SIGINT, @act, nil);
sigaction(SIGTERM, @act, nil);
end;
procedure SignalHandle(sig_num: integer);
begin
// Writeln('(* sig_num *) : ' + IntToStr(sig_num));
// Writeln('(* SIGTERM *) : ' + IntToStr(SIGTERM));
// Writeln('(* SIGINT *) : ' + IntToStr(SIGINT));
case (sig_num) of
-4, SIGTERM:
begin
Writeln('(* kill *)');
end;
SIGINT:
begin
Writeln('(* Ctrl+C *)');
end;
end;
end;
begin
// Setting signal
SignalSet(@SignalHandle);
Repeat
WriteLn('heheheheheeheheh');
Sleep(10000);
Until False;
end.
Offline