#1 2014-11-21 15:31:55

ComingNine
Member
Registered: 2010-07-29
Posts: 240

Using FPC under linux x64, console application fails to receive SIGINT

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

#2 2014-11-21 16:47:54

AOG
Member
Registered: 2014-02-24
Posts: 342

Re: Using FPC under linux x64, console application fails to receive SIGINT

First, try to include Synopse.inc into your program, to see if the FPC settings inside have influence.
Please report back.

Offline

#3 2014-11-22 00:50:19

ComingNine
Member
Registered: 2010-07-29
Posts: 240

Re: Using FPC under linux x64, console application fails to receive SIGINT

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

#4 2014-11-22 07:03:43

AOG
Member
Registered: 2014-02-24
Posts: 342

Re: Using FPC under linux x64, console application fails to receive SIGINT

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

#5 2014-11-22 08:17:59

ComingNine
Member
Registered: 2010-07-29
Posts: 240

Re: Using FPC under linux x64, console application fails to receive SIGINT

Thank you for your time and comments !

With Synopse.inc and without SynCommons, the console app can respond to SIGINT.

Offline

#6 2014-11-22 15:16:03

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 9,214
Website

Re: Using FPC under linux x64, console application fails to receive SIGINT

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.

Offline

#7 2014-11-22 16:13:44

ComingNine
Member
Registered: 2010-07-29
Posts: 240

Re: Using FPC under linux x64, console application fails to receive SIGINT

Wow ! Thank you very much for your help in identifying the problem !... big_smile

Offline

#8 2014-11-22 18:02:52

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 9,214
Website

Re: Using FPC under linux x64, console application fails to receive SIGINT

You can thank Google search, here.
smile

Offline

#9 2014-11-23 09:06:17

AOG
Member
Registered: 2014-02-24
Posts: 342

Re: Using FPC under linux x64, console application fails to receive SIGINT

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

#10 2014-11-23 09:11:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 9,214
Website

Re: Using FPC under linux x64, console application fails to receive SIGINT

... 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.

Offline

#11 2014-11-23 11:19:06

AOG
Member
Registered: 2014-02-24
Posts: 342

Re: Using FPC under linux x64, console application fails to receive SIGINT

If you can spare the time ... this would be a nice and welcome change !

Offline

#12 2014-11-23 17:34:30

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 9,214
Website

Re: Using FPC under linux x64, console application fails to receive SIGINT

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

Offline

#13 2014-11-24 06:59:03

ComingNine
Member
Registered: 2010-07-29
Posts: 240

Re: Using FPC under linux x64, console application fails to receive SIGINT

Excellent excellent news ! Thank you very much for your great work ! smile

Offline

#14 2015-09-22 09:27:57

ComingNine
Member
Registered: 2010-07-29
Posts: 240

Re: Using FPC under linux x64, console application fails to receive SIGINT

In case it might be useful, the following link contains an working example of signal trapping for Kylix (not just Ctrl+C). smile

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

Board footer

Powered by FluxBB