View Issue Details

IDProjectCategoryView StatusLast Update
0035846FPCRTLpublic2019-07-14 10:38
ReporterCyraxAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionwon't fix 
PlatformLinux x86_64OSArchOS Version3.17.4-1
Product Version3.3.1Product Buildr42348 
Target VersionFixed in Version 
Summary0035846: [patch] Better signal handling under linux systems
DescriptionAttached patch will improve signal handling to exceptions and thus allows program to handle better how it will save resources when receiving SIGQUIT/SIGTERM/SIGINT signals.
Tagspatch
Fixed in Revision
FPCOldBugId
FPCTarget-
Attached Files
  • linux_signal_fix.diff (13,682 bytes)
    diff --git a/packages/fcl-extra/src/unix/daemonapp.inc b/packages/fcl-extra/src/unix/daemonapp.inc
    index a33bf85991..7ce0b75a24 100644
    --- a/packages/fcl-extra/src/unix/daemonapp.inc
    +++ b/packages/fcl-extra/src/unix/daemonapp.inc
    @@ -229,7 +229,8 @@ Procedure SysInitDaemonApp;
       begin
         FillChar(New,SizeOf(Sigactionrec),#0);
         FillChar(Old,SizeOf(Sigactionrec),#0);
    -    New.sa_handler:=@DoShutDown;
    +    New.sa_handlers.sa_sigaction:=@DoShutDown;
    +    New.sa_flags:=SA_SIGINFO;
         fpSigaction(aSig,@New,@Old);
       end;
     
    diff --git a/packages/rtl-extra/src/unix/gpm.pp b/packages/rtl-extra/src/unix/gpm.pp
    index 0de0063c1e..0fdc56ea33 100644
    --- a/packages/rtl-extra/src/unix/gpm.pp
    +++ b/packages/rtl-extra/src/unix/gpm.pp
    @@ -341,9 +341,9 @@ procedure gpm_winch_hook(signum:longint;SigInfo: PSigInfo; SigContext: PSigConte
     var win:winsize;
     
     begin
    -  if (sigactionhandler(SIG_IGN)<>gpm_saved_winch_hook.sa_handler) and
    -     (sigactionhandler(SIG_DFL)<>gpm_saved_winch_hook.sa_handler) then
    -    gpm_saved_winch_hook.sa_handler(signum,nil,nil);
    +  if (sigactionhandler(SIG_IGN)<>gpm_saved_winch_hook.sa_handlers.sa_sigaction) and
    +     (sigactionhandler(SIG_DFL)<>gpm_saved_winch_hook.sa_handlers.sa_sigaction) then
    +    gpm_saved_winch_hook.sa_handlers.sa_sigaction(signum,nil,nil);
       if fpioctl(gpm_consolefd,TIOCGWINSZ,@win)=-1 then
         exit;
       if (win.ws_col=0) or (win.ws_row=0) then
    @@ -363,6 +363,7 @@ var conn:Tgpmconnect;
         success:boolean;
     
     begin
    +  fillchar(sa, sizeof(sigactionrec), 0);
       fpsigemptyset(new_sigset);
       fpsigaddset(new_sigset,SIGTSTP);
       fpsigprocmask(SIG_BLOCK,new_sigset,old_sigset);
    @@ -384,8 +385,8 @@ begin
     
       { Reincarnation. Prepare for another death early. }
       fpsigemptyset(sa.sa_mask);
    -  sa.sa_handler:=@gpm_suspend_hook;
    -  sa.sa_flags:=SA_NOMASK;
    +  sa.sa_handlers.sa_sigaction:=@gpm_suspend_hook;
    +  sa.sa_flags:=SA_NOMASK or SA_SIGINFO;
       fpsigaction(SIGTSTP,@sa,nil);
     
       { Pop the gpm stack by closing the useless connection }
    @@ -415,6 +416,8 @@ begin
       tty:='';
       options.consolename:='';
     
    +  fillchar(sa, sizeof(sigactionrec), 0);
    +
     {   gpm_report(GPM_PR_DEBUG,"VC: %d",flag);}
     
       {....................................... First of all, check xterm}
    @@ -575,21 +578,22 @@ begin
           fpsigemptyset(sa.sa_mask);
     
           { And the winch (window-resize) hook .. }
    -      sa.sa_handler:=@gpm_winch_hook;
    -      sa.sa_flags:=0;
    +      sa.sa_handlers.sa_sigaction:=@gpm_winch_hook;
    +      sa.sa_flags:=SA_SIGINFO;
           fpsigaction(SIGWINCH,@sa,@gpm_saved_winch_hook);
     
           if gpm_flag then
             begin
              { Install suspend hook }
    -         sa.sa_handler:=sigactionhandler(SIG_IGN);
    +         sa.sa_handlers.sa_sigaction:=sigactionhandler(SIG_IGN);
              fpsigaction(SIGTSTP,@sa,@gpm_saved_suspend_hook);
     
              {if signal was originally ignored, job control is not supported}
    -         if gpm_saved_suspend_hook.sa_handler<>sigactionhandler(SIG_IGN) then
    +         if gpm_saved_suspend_hook.sa_handlers.sa_sigaction<>sigactionhandler(SIG_IGN) then
                begin
    -            sa.sa_flags:=SA_NOMASK;
    -            sa.sa_handler:=@gpm_suspend_hook;
    +            fillchar(sa, sizeof(sigactionrec), 0);
    +            sa.sa_flags:=SA_NOMASK or SA_SIGINFO;
    +            sa.sa_handlers.sa_sigaction:=@gpm_suspend_hook;
                 fpsigaction(SIGTSTP,@sa,nil);
                end;
             end;
    diff --git a/rtl/linux/bunxsysc.inc b/rtl/linux/bunxsysc.inc
    index 280705ab1a..bb2b7081da 100644
    --- a/rtl/linux/bunxsysc.inc
    +++ b/rtl/linux/bunxsysc.inc
    @@ -151,6 +151,7 @@ var time_to_sleep,time_remaining : timespec;
     begin
             time_to_sleep.tv_sec := seconds;
             time_to_sleep.tv_nsec := 0;
    +        fillchar(oact, sizeof(sigactionrec), 0);
              fpsigemptyset(nset);
              fpsigaddset  (nset,SIGCHLD);
              if fpsigprocmask(SIG_BLOCK,@nset,@oset)=-1 Then
    @@ -166,7 +167,7 @@ begin
                     fpseterrno(oerrno);
                     exit(cuint(-1));
                   End;
    -            if oact.sa_handler=SigActionhandler(SIG_IGN) Then
    +            if oact.sa_handlers.sa_handler=signalhandler(SIG_IGN) Then
                  Begin
                    fpsleep:=fpnanosleep(@time_to_sleep, @time_remaining);
                    oerrno:=fpgeterrno;
    diff --git a/rtl/linux/i386/sighnd.inc b/rtl/linux/i386/sighnd.inc
    index 4a7a0dd3f3..ffe262fac5 100644
    --- a/rtl/linux/i386/sighnd.inc
    +++ b/rtl/linux/i386/sighnd.inc
    @@ -105,6 +105,8 @@ begin
             res:=217;
         SIGQUIT:
             res:=233;
    +    SIGTERM:
    +        res:=237;
       end;
       reenable_signal(sig);
     { give runtime error at the position where the signal was raised }
    diff --git a/rtl/linux/signal.inc b/rtl/linux/signal.inc
    index 74cae35346..c48b3a5683 100644
    --- a/rtl/linux/signal.inc
    +++ b/rtl/linux/signal.inc
    @@ -231,11 +231,17 @@ type
       tsigactionhandler = sigactionhandler_t;
       tsigrestorerhandler = sigrestorerhandler_t;
     
    +  sigactionrec_ = record
    +    case byte of
    +      0 : (sa_handler : signalhandler_t);
    +      1 : (sa_sigaction: sigactionhandler_t);
    +  end;
    +
       psigactionrec = ^sigactionrec;
     
     {$ifdef FPC_USE_LIBC}  // libc order is different ?
       sigactionrec = record
    -    sa_handler: sigactionhandler_t;
    +    sa_handlers: sigactionrec_;
         sa_mask: sigset_t;
         sa_flags: cint;
         sa_restorer: sigrestorerhandler_t;
    @@ -244,14 +250,14 @@ type
       {$ifdef cpumips}
       sigactionrec = record
         sa_flags: cuint;
    -    sa_handler: sigactionhandler_t;
    +    sa_handlers: sigactionrec_;
         sa_mask: sigset_t;
         sa_restorer: sigrestorerhandler_t; { Doesn't seem to exist on MIPS }
         sa_resv :  array [0..0] of cint;
       end;
       {$else not mips}
       sigactionrec = record
    -    sa_handler: sigactionhandler_t;
    +    sa_handlers : sigactionrec_;
         sa_flags: culong;
         sa_restorer: sigrestorerhandler_t;
         sa_mask: sigset_t;
    diff --git a/rtl/linux/system.pp b/rtl/linux/system.pp
    index 110fba7e91..205d0f442b 100644
    --- a/rtl/linux/system.pp
    +++ b/rtl/linux/system.pp
    @@ -553,14 +553,15 @@ end;
     procedure InstallDefaultSignalHandler(signum: longint; out oldact: SigActionRec); public name '_FPC_INSTALLDEFAULTSIGHANDLER';
     var
       act: SigActionRec;
    +  aresult : cint;
     begin
       { Initialize the sigaction structure }
       { all flags and information set to zero }
       FillChar(act, sizeof(SigActionRec),0);
       { initialize handler                    }
    -  act.sa_handler := SigActionHandler(@SignalToRunError);
    +  act.sa_handlers.sa_sigaction := SigActionHandler(@SignalToRunError);
       act.sa_flags:=SA_SIGINFO;
    -  FpSigAction(signum,@act,@oldact);
    +  aresult := FpSigAction(signum,@act,@oldact);
     end;
     
     var
    @@ -568,6 +569,9 @@ var
       oldsigsegv: SigActionRec; public name '_FPC_OLDSIGSEGV';
       oldsigbus: SigActionRec; public name '_FPC_OLDSIGBUS';
       oldsigill: SigActionRec; public name '_FPC_OLDSIGILL';
    +  oldsigterm: SigActionRec; public name '_FPC_OLDSIGTERM';
    +  oldsigquit: SigActionRec; public name '_FPC_OLDSIGQUIT';
    +  oldsigint: SigActionRec; public name '_FPC_OLDSIGINT';
     
     Procedure InstallSignals;
     begin
    @@ -575,6 +579,9 @@ begin
       InstallDefaultSignalHandler(SIGSEGV,oldsigsegv);
       InstallDefaultSignalHandler(SIGBUS,oldsigbus);
       InstallDefaultSignalHandler(SIGILL,oldsigill);
    +  InstallDefaultSignalHandler(SIGTERM,oldsigterm);
    +  InstallDefaultSignalHandler(SIGQUIT,oldsigquit);
    +  InstallDefaultSignalHandler(SIGINT,oldsigint);
     end;
     
     procedure SysInitStdIO;
    @@ -595,6 +602,9 @@ begin
       FpSigAction(SIGSEGV,@oldsigsegv,nil);
       FpSigAction(SIGBUS,@oldsigbus,nil);
       FpSigAction(SIGILL,@oldsigill,nil);
    +  FpSigAction(SIGTERM,@oldsigterm,nil);
    +  FpSigAction(SIGQUIT,@oldsigquit,nil);
    +  FpSigAction(SIGINT,@oldsigint,nil);
     end;
     
     
    diff --git a/rtl/linux/x86_64/sighnd.inc b/rtl/linux/x86_64/sighnd.inc
    index da570a90d5..403d8b0d25 100644
    --- a/rtl/linux/x86_64/sighnd.inc
    +++ b/rtl/linux/x86_64/sighnd.inc
    @@ -106,10 +106,12 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigCon
           SIGBUS,
           SIGSEGV:
             res:=216;
    -    SIGINT:
    +      SIGINT:
             res:=217;
    -    SIGQUIT:
    +      SIGQUIT:
             res:=233;
    +      SIGTERM:
    +        res:=237;
         end;
         reenable_signal(sig);
         if res<>0 then
    diff --git a/rtl/objpas/sysconst.pp b/rtl/objpas/sysconst.pp
    index 908572516b..af67399856 100644
    --- a/rtl/objpas/sysconst.pp
    +++ b/rtl/objpas/sysconst.pp
    @@ -89,6 +89,7 @@ const
       SNoDynLibsSupport      = 'Dynamic libraries not supported. Recompile program with dynamic library driver.';
       SMissingWStringManager = 'Widestring manager not available. Recompile program with appropriate manager.';
       SSigQuit               = 'SIGQUIT signal received.';
    +  SSigTerm               = 'SIGTERM signal received.';
       SObjectCheckError      = 'Object reference is Nil';
       SOSError               = 'System error, (OS Code %d):'+LineEnding+'%s';
       SOutOfMemory           = 'Out of memory';
    diff --git a/rtl/objpas/sysutils/sysutilh.inc b/rtl/objpas/sysutils/sysutilh.inc
    index c8614493ce..4fc6fec820 100644
    --- a/rtl/objpas/sysutils/sysutilh.inc
    +++ b/rtl/objpas/sysutils/sysutilh.inc
    @@ -194,6 +194,7 @@ type
        EObjectCheck     = Class(Exception);
        EThreadError     = Class(Exception);
        ESigQuit         = Class(Exception);
    +   ESigTerm         = Class(Exception);
     
        EPropReadOnly = class(Exception);
        EPropWriteOnly = class(Exception);
    diff --git a/rtl/objpas/sysutils/sysutils.inc b/rtl/objpas/sysutils/sysutils.inc
    index aa5b8f0a06..1f34ff8683 100644
    --- a/rtl/objpas/sysutils/sysutils.inc
    +++ b/rtl/objpas/sysutils/sysutils.inc
    @@ -340,7 +340,7 @@ type
       end;
     
     const
    -  exceptmap: array[0..30] of TExceptMapEntry = (
    +  exceptmap: array[0..31] of TExceptMapEntry = (
         (code: 200; cls: EDivByZero;     msg: @SDivByZero),
         (code: 201; cls: ERangeError;    msg: @SRangeError),
         (code: 202; cls: EStackOverflow; msg: @SStackOverflow),
    @@ -372,7 +372,8 @@ const
         (code: 233; cls: ESigQuit; msg: @SSigQuit),
         (code: 234; cls: ENoWideStringSupport; msg: @SMissingWStringManager),
         (code: 235; cls: ENoDynLibsSupport; msg: @SNoDynLibsSupport),
    -    (code: 236; cls: EThreadError; msg: @SThreadError)
    +    (code: 236; cls: EThreadError; msg: @SThreadError),
    +    (code: 237; cls: ESigTerm; msg: @SSigTerm)
       );
     
     function FindExceptMapEntry(err: longint): PExceptMapEntry;
    diff --git a/rtl/unix/bunxovl.inc b/rtl/unix/bunxovl.inc
    index 12025aad32..0969f026bc 100644
    --- a/rtl/unix/bunxovl.inc
    +++ b/rtl/unix/bunxovl.inc
    @@ -203,9 +203,9 @@ Function FpSignal(signum:longint;Handler:signalhandler):signalhandler;
     var sa,osa : sigactionrec;
     
     begin
    -     sa.sa_handler:=SigActionHandler(handler);
    -     FillChar(sa.sa_mask,sizeof(sa.sa_mask),#0);
    -     sa.sa_flags := 0;
    +     fillchar(sa, sizeof(sigactionrec), 0);
    +     fillchar(osa, sizeof(sigactionrec), 0);
    +     sa.sa_handlers.sa_handler:=signalhandler(handler);
     {     if (sigintr and signum) =0 then
      {restart behaviour needs libc}
           sa.sa_flags :=sa.sa_flags or SA_RESTART;
    @@ -214,7 +214,7 @@ begin
          if fpgetErrNo<>0 then
            fpsignal:=NIL
          else
    -       fpsignal:=signalhandler(osa.sa_handler);
    +       fpsignal:=signalhandler(osa.sa_handlers.sa_handler);
     end;
     
     {$ifdef FPC_USE_LIBC} // can't remember why this is the case. Might be legacy.
    diff --git a/rtl/unix/sysutils.pp b/rtl/unix/sysutils.pp
    index 29d64d081f..dc2c854765 100644
    --- a/rtl/unix/sysutils.pp
    +++ b/rtl/unix/sysutils.pp
    @@ -128,7 +128,7 @@ function InternalInquireSignal(RtlSigNum: Integer; out act: SigActionRec; fromin
                   begin
                     { check whether the installed signal handler is still ours }
     {$if not defined(aix) and (not defined(linux) or not defined(cpupowerpc64) or (defined(_call_elf) and (_call_elf = 2)))}
    -                if (pointer(act.sa_handler)=pointer(@defaultsighandler)) then
    +                if (pointer(act.sa_handlers.sa_sigaction)=pointer(@defaultsighandler)) then
     {$else}
                     { on aix and linux/ppc64 (ELFv1), procedure addresses are
                       actually descriptors -> check whether the code addresses
    @@ -151,7 +151,7 @@ function InternalInquireSignal(RtlSigNum: Integer; out act: SigActionRec; fromin
                     if (byte(RtlSigNum) in [RTL_SIGFPE,RTL_SIGSEGV,RTL_SIGILL,RTL_SIGBUS]) then
                       begin
     {$if not defined(aix) and (not defined(linux) or not defined(cpupowerpc64) or (defined(_call_elf) and (_call_elf = 2)))}
    -                    if (pointer(act.sa_handler)=pointer(@defaultsighandler)) then
    +                    if (pointer(act.sa_handlers.sa_sigaction)=pointer(@defaultsighandler)) then
     {$else}
                         if (ppointer(act.sa_handler)^=ppointer(@defaultsighandler)^) then
     {$endif}
    @@ -272,7 +272,7 @@ procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);
                 else
                   begin
                     fillchar(act,sizeof(act),0);
    -                pointer(act.sa_handler):=pointer(SIG_DFL);
    +                pointer(act.sa_handlers.sa_handler):=pointer(SIG_DFL);
                   end;
                 if (fpsigaction(rtlsig2ossig[i],@act,nil)=0) then
                   siginfo[i].hooked:=false;
    diff --git a/rtl/unix/unix.pp b/rtl/unix/unix.pp
    index f41b1a1b18..10e8fd5665 100644
    --- a/rtl/unix/unix.pp
    +++ b/rtl/unix/unix.pp
    @@ -362,7 +362,10 @@ begin { Changes as above }
       {$ifndef SHELL_USE_FPEXEC}
         p:=CreateShellArgv(command);
       {$endif}
    -  ign.sa_handler:=SigActionHandler(SIG_IGN);
    +  fillchar(ign, sizeof(SigactionRec), 0);
    +  fillchar(intact, sizeof(SigactionRec), 0);
    +  fillchar(quitact, sizeof(SigactionRec), 0);
    +  ign.sa_handlers.sa_handler:=signalhandler(SIG_IGN);
       fpsigemptyset(ign.sa_mask);
       ign.sa_flags:=0;
       fpsigaction(SIGINT, @ign, @intact);
    
    linux_signal_fix.diff (13,682 bytes)

Activities

Cyrax

2019-07-13 20:14

reporter  

linux_signal_fix.diff (13,682 bytes)
diff --git a/packages/fcl-extra/src/unix/daemonapp.inc b/packages/fcl-extra/src/unix/daemonapp.inc
index a33bf85991..7ce0b75a24 100644
--- a/packages/fcl-extra/src/unix/daemonapp.inc
+++ b/packages/fcl-extra/src/unix/daemonapp.inc
@@ -229,7 +229,8 @@ Procedure SysInitDaemonApp;
   begin
     FillChar(New,SizeOf(Sigactionrec),#0);
     FillChar(Old,SizeOf(Sigactionrec),#0);
-    New.sa_handler:=@DoShutDown;
+    New.sa_handlers.sa_sigaction:=@DoShutDown;
+    New.sa_flags:=SA_SIGINFO;
     fpSigaction(aSig,@New,@Old);
   end;
 
diff --git a/packages/rtl-extra/src/unix/gpm.pp b/packages/rtl-extra/src/unix/gpm.pp
index 0de0063c1e..0fdc56ea33 100644
--- a/packages/rtl-extra/src/unix/gpm.pp
+++ b/packages/rtl-extra/src/unix/gpm.pp
@@ -341,9 +341,9 @@ procedure gpm_winch_hook(signum:longint;SigInfo: PSigInfo; SigContext: PSigConte
 var win:winsize;
 
 begin
-  if (sigactionhandler(SIG_IGN)<>gpm_saved_winch_hook.sa_handler) and
-     (sigactionhandler(SIG_DFL)<>gpm_saved_winch_hook.sa_handler) then
-    gpm_saved_winch_hook.sa_handler(signum,nil,nil);
+  if (sigactionhandler(SIG_IGN)<>gpm_saved_winch_hook.sa_handlers.sa_sigaction) and
+     (sigactionhandler(SIG_DFL)<>gpm_saved_winch_hook.sa_handlers.sa_sigaction) then
+    gpm_saved_winch_hook.sa_handlers.sa_sigaction(signum,nil,nil);
   if fpioctl(gpm_consolefd,TIOCGWINSZ,@win)=-1 then
     exit;
   if (win.ws_col=0) or (win.ws_row=0) then
@@ -363,6 +363,7 @@ var conn:Tgpmconnect;
     success:boolean;
 
 begin
+  fillchar(sa, sizeof(sigactionrec), 0);
   fpsigemptyset(new_sigset);
   fpsigaddset(new_sigset,SIGTSTP);
   fpsigprocmask(SIG_BLOCK,new_sigset,old_sigset);
@@ -384,8 +385,8 @@ begin
 
   { Reincarnation. Prepare for another death early. }
   fpsigemptyset(sa.sa_mask);
-  sa.sa_handler:=@gpm_suspend_hook;
-  sa.sa_flags:=SA_NOMASK;
+  sa.sa_handlers.sa_sigaction:=@gpm_suspend_hook;
+  sa.sa_flags:=SA_NOMASK or SA_SIGINFO;
   fpsigaction(SIGTSTP,@sa,nil);
 
   { Pop the gpm stack by closing the useless connection }
@@ -415,6 +416,8 @@ begin
   tty:='';
   options.consolename:='';
 
+  fillchar(sa, sizeof(sigactionrec), 0);
+
 {   gpm_report(GPM_PR_DEBUG,"VC: %d",flag);}
 
   {....................................... First of all, check xterm}
@@ -575,21 +578,22 @@ begin
       fpsigemptyset(sa.sa_mask);
 
       { And the winch (window-resize) hook .. }
-      sa.sa_handler:=@gpm_winch_hook;
-      sa.sa_flags:=0;
+      sa.sa_handlers.sa_sigaction:=@gpm_winch_hook;
+      sa.sa_flags:=SA_SIGINFO;
       fpsigaction(SIGWINCH,@sa,@gpm_saved_winch_hook);
 
       if gpm_flag then
         begin
          { Install suspend hook }
-         sa.sa_handler:=sigactionhandler(SIG_IGN);
+         sa.sa_handlers.sa_sigaction:=sigactionhandler(SIG_IGN);
          fpsigaction(SIGTSTP,@sa,@gpm_saved_suspend_hook);
 
          {if signal was originally ignored, job control is not supported}
-         if gpm_saved_suspend_hook.sa_handler<>sigactionhandler(SIG_IGN) then
+         if gpm_saved_suspend_hook.sa_handlers.sa_sigaction<>sigactionhandler(SIG_IGN) then
            begin
-            sa.sa_flags:=SA_NOMASK;
-            sa.sa_handler:=@gpm_suspend_hook;
+            fillchar(sa, sizeof(sigactionrec), 0);
+            sa.sa_flags:=SA_NOMASK or SA_SIGINFO;
+            sa.sa_handlers.sa_sigaction:=@gpm_suspend_hook;
             fpsigaction(SIGTSTP,@sa,nil);
            end;
         end;
diff --git a/rtl/linux/bunxsysc.inc b/rtl/linux/bunxsysc.inc
index 280705ab1a..bb2b7081da 100644
--- a/rtl/linux/bunxsysc.inc
+++ b/rtl/linux/bunxsysc.inc
@@ -151,6 +151,7 @@ var time_to_sleep,time_remaining : timespec;
 begin
         time_to_sleep.tv_sec := seconds;
         time_to_sleep.tv_nsec := 0;
+        fillchar(oact, sizeof(sigactionrec), 0);
          fpsigemptyset(nset);
          fpsigaddset  (nset,SIGCHLD);
          if fpsigprocmask(SIG_BLOCK,@nset,@oset)=-1 Then
@@ -166,7 +167,7 @@ begin
                 fpseterrno(oerrno);
                 exit(cuint(-1));
               End;
-            if oact.sa_handler=SigActionhandler(SIG_IGN) Then
+            if oact.sa_handlers.sa_handler=signalhandler(SIG_IGN) Then
              Begin
                fpsleep:=fpnanosleep(@time_to_sleep, @time_remaining);
                oerrno:=fpgeterrno;
diff --git a/rtl/linux/i386/sighnd.inc b/rtl/linux/i386/sighnd.inc
index 4a7a0dd3f3..ffe262fac5 100644
--- a/rtl/linux/i386/sighnd.inc
+++ b/rtl/linux/i386/sighnd.inc
@@ -105,6 +105,8 @@ begin
         res:=217;
     SIGQUIT:
         res:=233;
+    SIGTERM:
+        res:=237;
   end;
   reenable_signal(sig);
 { give runtime error at the position where the signal was raised }
diff --git a/rtl/linux/signal.inc b/rtl/linux/signal.inc
index 74cae35346..c48b3a5683 100644
--- a/rtl/linux/signal.inc
+++ b/rtl/linux/signal.inc
@@ -231,11 +231,17 @@ type
   tsigactionhandler = sigactionhandler_t;
   tsigrestorerhandler = sigrestorerhandler_t;
 
+  sigactionrec_ = record
+    case byte of
+      0 : (sa_handler : signalhandler_t);
+      1 : (sa_sigaction: sigactionhandler_t);
+  end;
+
   psigactionrec = ^sigactionrec;
 
 {$ifdef FPC_USE_LIBC}  // libc order is different ?
   sigactionrec = record
-    sa_handler: sigactionhandler_t;
+    sa_handlers: sigactionrec_;
     sa_mask: sigset_t;
     sa_flags: cint;
     sa_restorer: sigrestorerhandler_t;
@@ -244,14 +250,14 @@ type
   {$ifdef cpumips}
   sigactionrec = record
     sa_flags: cuint;
-    sa_handler: sigactionhandler_t;
+    sa_handlers: sigactionrec_;
     sa_mask: sigset_t;
     sa_restorer: sigrestorerhandler_t; { Doesn't seem to exist on MIPS }
     sa_resv :  array [0..0] of cint;
   end;
   {$else not mips}
   sigactionrec = record
-    sa_handler: sigactionhandler_t;
+    sa_handlers : sigactionrec_;
     sa_flags: culong;
     sa_restorer: sigrestorerhandler_t;
     sa_mask: sigset_t;
diff --git a/rtl/linux/system.pp b/rtl/linux/system.pp
index 110fba7e91..205d0f442b 100644
--- a/rtl/linux/system.pp
+++ b/rtl/linux/system.pp
@@ -553,14 +553,15 @@ end;
 procedure InstallDefaultSignalHandler(signum: longint; out oldact: SigActionRec); public name '_FPC_INSTALLDEFAULTSIGHANDLER';
 var
   act: SigActionRec;
+  aresult : cint;
 begin
   { Initialize the sigaction structure }
   { all flags and information set to zero }
   FillChar(act, sizeof(SigActionRec),0);
   { initialize handler                    }
-  act.sa_handler := SigActionHandler(@SignalToRunError);
+  act.sa_handlers.sa_sigaction := SigActionHandler(@SignalToRunError);
   act.sa_flags:=SA_SIGINFO;
-  FpSigAction(signum,@act,@oldact);
+  aresult := FpSigAction(signum,@act,@oldact);
 end;
 
 var
@@ -568,6 +569,9 @@ var
   oldsigsegv: SigActionRec; public name '_FPC_OLDSIGSEGV';
   oldsigbus: SigActionRec; public name '_FPC_OLDSIGBUS';
   oldsigill: SigActionRec; public name '_FPC_OLDSIGILL';
+  oldsigterm: SigActionRec; public name '_FPC_OLDSIGTERM';
+  oldsigquit: SigActionRec; public name '_FPC_OLDSIGQUIT';
+  oldsigint: SigActionRec; public name '_FPC_OLDSIGINT';
 
 Procedure InstallSignals;
 begin
@@ -575,6 +579,9 @@ begin
   InstallDefaultSignalHandler(SIGSEGV,oldsigsegv);
   InstallDefaultSignalHandler(SIGBUS,oldsigbus);
   InstallDefaultSignalHandler(SIGILL,oldsigill);
+  InstallDefaultSignalHandler(SIGTERM,oldsigterm);
+  InstallDefaultSignalHandler(SIGQUIT,oldsigquit);
+  InstallDefaultSignalHandler(SIGINT,oldsigint);
 end;
 
 procedure SysInitStdIO;
@@ -595,6 +602,9 @@ begin
   FpSigAction(SIGSEGV,@oldsigsegv,nil);
   FpSigAction(SIGBUS,@oldsigbus,nil);
   FpSigAction(SIGILL,@oldsigill,nil);
+  FpSigAction(SIGTERM,@oldsigterm,nil);
+  FpSigAction(SIGQUIT,@oldsigquit,nil);
+  FpSigAction(SIGINT,@oldsigint,nil);
 end;
 
 
diff --git a/rtl/linux/x86_64/sighnd.inc b/rtl/linux/x86_64/sighnd.inc
index da570a90d5..403d8b0d25 100644
--- a/rtl/linux/x86_64/sighnd.inc
+++ b/rtl/linux/x86_64/sighnd.inc
@@ -106,10 +106,12 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigCon
       SIGBUS,
       SIGSEGV:
         res:=216;
-    SIGINT:
+      SIGINT:
         res:=217;
-    SIGQUIT:
+      SIGQUIT:
         res:=233;
+      SIGTERM:
+        res:=237;
     end;
     reenable_signal(sig);
     if res<>0 then
diff --git a/rtl/objpas/sysconst.pp b/rtl/objpas/sysconst.pp
index 908572516b..af67399856 100644
--- a/rtl/objpas/sysconst.pp
+++ b/rtl/objpas/sysconst.pp
@@ -89,6 +89,7 @@ const
   SNoDynLibsSupport      = 'Dynamic libraries not supported. Recompile program with dynamic library driver.';
   SMissingWStringManager = 'Widestring manager not available. Recompile program with appropriate manager.';
   SSigQuit               = 'SIGQUIT signal received.';
+  SSigTerm               = 'SIGTERM signal received.';
   SObjectCheckError      = 'Object reference is Nil';
   SOSError               = 'System error, (OS Code %d):'+LineEnding+'%s';
   SOutOfMemory           = 'Out of memory';
diff --git a/rtl/objpas/sysutils/sysutilh.inc b/rtl/objpas/sysutils/sysutilh.inc
index c8614493ce..4fc6fec820 100644
--- a/rtl/objpas/sysutils/sysutilh.inc
+++ b/rtl/objpas/sysutils/sysutilh.inc
@@ -194,6 +194,7 @@ type
    EObjectCheck     = Class(Exception);
    EThreadError     = Class(Exception);
    ESigQuit         = Class(Exception);
+   ESigTerm         = Class(Exception);
 
    EPropReadOnly = class(Exception);
    EPropWriteOnly = class(Exception);
diff --git a/rtl/objpas/sysutils/sysutils.inc b/rtl/objpas/sysutils/sysutils.inc
index aa5b8f0a06..1f34ff8683 100644
--- a/rtl/objpas/sysutils/sysutils.inc
+++ b/rtl/objpas/sysutils/sysutils.inc
@@ -340,7 +340,7 @@ type
   end;
 
 const
-  exceptmap: array[0..30] of TExceptMapEntry = (
+  exceptmap: array[0..31] of TExceptMapEntry = (
     (code: 200; cls: EDivByZero;     msg: @SDivByZero),
     (code: 201; cls: ERangeError;    msg: @SRangeError),
     (code: 202; cls: EStackOverflow; msg: @SStackOverflow),
@@ -372,7 +372,8 @@ const
     (code: 233; cls: ESigQuit; msg: @SSigQuit),
     (code: 234; cls: ENoWideStringSupport; msg: @SMissingWStringManager),
     (code: 235; cls: ENoDynLibsSupport; msg: @SNoDynLibsSupport),
-    (code: 236; cls: EThreadError; msg: @SThreadError)
+    (code: 236; cls: EThreadError; msg: @SThreadError),
+    (code: 237; cls: ESigTerm; msg: @SSigTerm)
   );
 
 function FindExceptMapEntry(err: longint): PExceptMapEntry;
diff --git a/rtl/unix/bunxovl.inc b/rtl/unix/bunxovl.inc
index 12025aad32..0969f026bc 100644
--- a/rtl/unix/bunxovl.inc
+++ b/rtl/unix/bunxovl.inc
@@ -203,9 +203,9 @@ Function FpSignal(signum:longint;Handler:signalhandler):signalhandler;
 var sa,osa : sigactionrec;
 
 begin
-     sa.sa_handler:=SigActionHandler(handler);
-     FillChar(sa.sa_mask,sizeof(sa.sa_mask),#0);
-     sa.sa_flags := 0;
+     fillchar(sa, sizeof(sigactionrec), 0);
+     fillchar(osa, sizeof(sigactionrec), 0);
+     sa.sa_handlers.sa_handler:=signalhandler(handler);
 {     if (sigintr and signum) =0 then
  {restart behaviour needs libc}
       sa.sa_flags :=sa.sa_flags or SA_RESTART;
@@ -214,7 +214,7 @@ begin
      if fpgetErrNo<>0 then
        fpsignal:=NIL
      else
-       fpsignal:=signalhandler(osa.sa_handler);
+       fpsignal:=signalhandler(osa.sa_handlers.sa_handler);
 end;
 
 {$ifdef FPC_USE_LIBC} // can't remember why this is the case. Might be legacy.
diff --git a/rtl/unix/sysutils.pp b/rtl/unix/sysutils.pp
index 29d64d081f..dc2c854765 100644
--- a/rtl/unix/sysutils.pp
+++ b/rtl/unix/sysutils.pp
@@ -128,7 +128,7 @@ function InternalInquireSignal(RtlSigNum: Integer; out act: SigActionRec; fromin
               begin
                 { check whether the installed signal handler is still ours }
 {$if not defined(aix) and (not defined(linux) or not defined(cpupowerpc64) or (defined(_call_elf) and (_call_elf = 2)))}
-                if (pointer(act.sa_handler)=pointer(@defaultsighandler)) then
+                if (pointer(act.sa_handlers.sa_sigaction)=pointer(@defaultsighandler)) then
 {$else}
                 { on aix and linux/ppc64 (ELFv1), procedure addresses are
                   actually descriptors -> check whether the code addresses
@@ -151,7 +151,7 @@ function InternalInquireSignal(RtlSigNum: Integer; out act: SigActionRec; fromin
                 if (byte(RtlSigNum) in [RTL_SIGFPE,RTL_SIGSEGV,RTL_SIGILL,RTL_SIGBUS]) then
                   begin
 {$if not defined(aix) and (not defined(linux) or not defined(cpupowerpc64) or (defined(_call_elf) and (_call_elf = 2)))}
-                    if (pointer(act.sa_handler)=pointer(@defaultsighandler)) then
+                    if (pointer(act.sa_handlers.sa_sigaction)=pointer(@defaultsighandler)) then
 {$else}
                     if (ppointer(act.sa_handler)^=ppointer(@defaultsighandler)^) then
 {$endif}
@@ -272,7 +272,7 @@ procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);
             else
               begin
                 fillchar(act,sizeof(act),0);
-                pointer(act.sa_handler):=pointer(SIG_DFL);
+                pointer(act.sa_handlers.sa_handler):=pointer(SIG_DFL);
               end;
             if (fpsigaction(rtlsig2ossig[i],@act,nil)=0) then
               siginfo[i].hooked:=false;
diff --git a/rtl/unix/unix.pp b/rtl/unix/unix.pp
index f41b1a1b18..10e8fd5665 100644
--- a/rtl/unix/unix.pp
+++ b/rtl/unix/unix.pp
@@ -362,7 +362,10 @@ begin { Changes as above }
   {$ifndef SHELL_USE_FPEXEC}
     p:=CreateShellArgv(command);
   {$endif}
-  ign.sa_handler:=SigActionHandler(SIG_IGN);
+  fillchar(ign, sizeof(SigactionRec), 0);
+  fillchar(intact, sizeof(SigactionRec), 0);
+  fillchar(quitact, sizeof(SigactionRec), 0);
+  ign.sa_handlers.sa_handler:=signalhandler(SIG_IGN);
   fpsigemptyset(ign.sa_mask);
   ign.sa_flags:=0;
   fpsigaction(SIGINT, @ign, @intact);
linux_signal_fix.diff (13,682 bytes)

Cyrax

2019-07-13 21:26

reporter   ~0117250

Forum thread : https://forum.lazarus.freepascal.org/index.php/topic,46067.msg327141/topicseen.html#new

Michael Van Canneyt

2019-07-14 10:38

administrator   ~0117256

In addition to catching an extra signal, this patch completely changes the signal handler record.
I will not apply this as it will destroy backwards compatibility.

You can use a typecast to coerce the handler.

I am also not sure that this should be done in sysutils: this will completely change the behaviour of existing programs.
If we do this, it must be very well documented.

Issue History

Date Modified Username Field Change
2019-07-13 20:14 Cyrax New Issue
2019-07-13 20:14 Cyrax File Added: linux_signal_fix.diff
2019-07-13 20:16 Cyrax Tag Attached: patch
2019-07-13 21:26 Cyrax Note Added: 0117250
2019-07-14 10:38 Michael Van Canneyt Assigned To => Michael Van Canneyt
2019-07-14 10:38 Michael Van Canneyt Status new => resolved
2019-07-14 10:38 Michael Van Canneyt Resolution open => won't fix
2019-07-14 10:38 Michael Van Canneyt FPCTarget => -
2019-07-14 10:38 Michael Van Canneyt Note Added: 0117256