Browse Source

add signal handler trampoline return for buggy OS like fedora core

git-svn-id: trunk@3311 -
micha 19 years ago
parent
commit
7911be08f5
3 changed files with 83 additions and 43 deletions
  1. 60 3
      rtl/linux/ossysc.inc
  2. 22 39
      rtl/linux/signal.inc
  3. 1 1
      rtl/unix/bunxovl.inc

+ 60 - 3
rtl/linux/ossysc.inc

@@ -208,8 +208,49 @@ asm
 end;
 {$endif cpusparc}
 
+{$if defined(cpui386) or defined(cpuarm) or defined(cpux86_64)}
+  {$define NEED_USER_TRAMPOLINE}
+{$endif}
+{$if defined(cpui386) or defined(cpuarm)}
+  {$define NEED_USER_TRAMPOLINE_RT_DIFFERENT}
+{$endif}
+
+{$ifdef NEED_USER_TRAMPOLINE}
+
+procedure linux_restore; cdecl; nostackframe; assembler;
+asm
+{$ifdef cpuarm}
+  swi __NR_sigreturn;
+{$endif}
+{$ifdef cpui386}
+  popl %eax
+  movl $syscall_nr_sigreturn, %eax
+  int $0x80
+{$endif}
+{$ifdef cpux86_64}
+  moq $syscall_nr_rt_sigreturn, %rax
+  syscall
+{$endif}
+end;
+
+{$endif}
+
+{$ifdef NEED_USER_TRAMPOLINE_RT_DIFFERENT}
+
+procedure linux_restore_rt; cdecl; nostackframe; assembler;
+asm
+{$ifdef cpuarm}                                                                                             
+  swi syscall_nr_rt_sigreturn                                                                               
+{$endif}
+{$ifdef cpui386}
+  movl $syscall_nr_rt_sigreturn, %eax
+  int $0x80
+{$endif}
+end;
+
+{$endif}
 
-function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint; [public, alias : 'FPC_SYSC_SIGACTION'];
+function Fpsigaction(sig: cint; new_action, old_action: psigactionrec): cint; [public, alias : 'FPC_SYSC_SIGACTION'];
 {
   Change action of process upon receipt of a signal.
   Signum specifies the signal (all except SigKill and SigStop).
@@ -219,9 +260,25 @@ function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint
 begin
 {$ifdef cpusparc}
   { Sparc has an extra stub parameter }
-  Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact),TSysParam(PtrInt(@Fprt_sigreturn_stub)-8),TSysParam(8));
+  Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(new_action),TSysParam(old_action),TSysParam(PtrInt(@Fprt_sigreturn_stub)-8),TSysParam(8));
 {$else cpusparc}
-  Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact),TSysParam(8));
+{$ifdef NEED_USER_TRAMPOLINE}
+  if new_action <> nil then
+  begin
+    // a different stack (SA_ONSTACK) requires sa_restorer field
+    if (new_action^.sa_flags and (SA_RESTORER or SA_ONSTACK)) = 0 then
+    begin
+      new_action^.sa_flags := new_action^.sa_flags or SA_RESTORER;
+{$ifdef NEED_USER_TRAMPOLINE_RT_DIFFERENT}
+      if (new_action^.sa_flags and SA_SIGINFO) <> 0 then
+        new_action^.sa_restorer := @linux_restore_rt
+      else
+{$endif}
+        new_action^.sa_restorer := @linux_restore;
+    end;                                                                                                    
+  end;                                                                                                      
+{$endif}
+  Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(new_action),TSysParam(old_action),TSysParam(8));
 {$endif cpusparc}
 end;
 

+ 22 - 39
rtl/linux/signal.inc

@@ -31,8 +31,8 @@ Const
   SA_NOCLDSTOP = 1;
   SA_NOCLDWAIT = 2;
   SA_SIGINFO   = 4;
-  SA_SHIRQ     = $04000000;
-  SA_STACK     = $08000000;
+  SA_RESTORER  = $04000000;
+  SA_ONSTACK   = $08000000;
   SA_RESTART   = $10000000;
   SA_INTERRUPT = $20000000;
   SA_NOMASK    = $40000000;
@@ -133,11 +133,9 @@ const
   SI_PAD_SIZE   = ((128 div sizeof(longint)) - 3);
 
 type
-  SigSet  =  array[0..wordsinsigset-1] of cuLong;
-  sigset_t= SigSet;
-  PSigSet = ^SigSet;
-  psigset_t=psigset;
-  TSigSet = SigSet;
+  sigset_t = array[0..wordsinsigset-1] of cuLong;
+  tsigset  = sigset_t;
+  psigset  = ^tsigset;
 
   psiginfo = ^tsiginfo;
   tsiginfo = record
@@ -181,37 +179,22 @@ type
 {$i sighndh.inc}
 
 type
-  SignalHandler   = Procedure(Sig : Longint);cdecl;
-  PSignalHandler  = ^SignalHandler;
-  SignalRestorer  = Procedure;cdecl;
-  PSignalRestorer = ^SignalRestorer;
-  SigActionHandler = procedure(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl;
-
-{$ifdef CPUARM}
-{$define NEWSIGNAL}
-{$endif CPUARM}
-
-{$ifdef CPUx86_64}
-{$define NEWSIGNAL}
-{$endif CPUx86_64}
-
-{$ifdef CPUPOWERPC64}
-{$define NEWSIGNAL}
-{$endif CPUPOWERPC64}
-
-  SigActionRec = packed record  // this is temporary for the migration
-    sa_handler : SigActionHandler;
-   {$ifdef NEWSIGNAL}
-    Sa_Flags    : culong;
-    Sa_restorer : SignalRestorer; { Obsolete - Don't use }
-    Sa_Mask     : SigSet;
-   {$else NEWSIGNAL}
-    Sa_Mask     : SigSet;
-    Sa_Flags    : cuLong;
-    Sa_restorer : SignalRestorer; { Obsolete - Don't use }
-   {$endif NEWSIGNAL}
+  signalhandler_t = procedure(signal: longint); cdecl;
+  sigactionhandler_t = procedure(signal: longint; info: psiginfo; context: psigcontext); cdecl;
+  sigrestorerhandler_t = procedure; cdecl;
+      
+  signalhandler = signalhandler_t;
+  sigactionhandler = sigactionhandler_t;
+  sigrestorerhandler = sigrestorerhandler_t;
+  tsignalhandler = signalhandler_t;
+  tsigactionhandler = sigactionhandler_t;
+  tsigrestorerhandler = sigrestorerhandler_t;
+  
+  psigactionrec = ^sigactionrec;
+  sigactionrec = packed record
+    sa_handler: sigactionhandler_t;
+    sa_flags: dword;
+    sa_restorer: sigrestorerhandler_t;
+    sa_mask: sigset_t;
   end;
-  TSigActionRec = SigActionRec;
-  PSigActionRec = ^SigActionRec;
-
 

+ 1 - 1
rtl/unix/bunxovl.inc

@@ -138,7 +138,7 @@ var sa,osa : sigactionrec;
 
 begin
      sa.sa_handler:=SigActionHandler(handler);
-     FillChar(sa.sa_mask,sizeof(sigset),#0);
+     FillChar(sa.sa_mask,sizeof(sa.sa_mask),#0);
      sa.sa_flags := 0;
 {     if (sigintr and signum) =0 then
  {restart behaviour needs libc}