Hi!

----

While trying to figure out why Solaris still have problems with
(realtime) signal handling I found another issue related to |errno|:
It seems that if syscalls are waiting and are then interrupted by a
signal the value of |errno| returned by the syscall looks different
than the errno value returned by the kernel for that syscall...
... after some digging I figured out that some platforms do not save
|errno| before calling the signal handler function and then restore it
when that function returns.

Attached (as "astksh20131010_sighandler_saverestore_errno001.diff") is
a simple patch which fixes that issue (and therefore fixes some
sporadic failures in ksh93 related to signal handling) ...

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.ma...@nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)
diff -r -u build_i386_64bit_debug/src/cmd/ksh93/sh/fault.c 
build_sigerrno/src/cmd/ksh93/sh/fault.c
--- src/cmd/ksh93/sh/fault.c    2013-08-14 23:31:23.000000000 +0200
+++ src/cmd/ksh93/sh/fault.c    2014-01-23 21:22:08.081397145 +0100
@@ -112,6 +112,7 @@
 void   sh_fault(register int sig)
 #endif
 {
+       int                     saved_errno = errno; /* many platforms do not 
save/restore errno for signal handlers */
        register Shell_t        *shp = sh_getinterp();
        register int            flag=0;
        register char           *trap;
@@ -135,21 +136,21 @@
                /* critical region, save and process later */
                if(!(shp->sigflag[sig]&SH_SIGIGNORE))
                        shp->savesig = sig;
-               return;
+               goto done;
        }
        /* handle ignored signals */
        if(trap && *trap==0)
-               return;
+               goto done;
        flag = shp->sigflag[sig]&~SH_SIGOFF;
        if(!trap)
        {
                if(sig==SIGINT && (shp->trapnote&SH_SIGIGNORE))
-                       return;
+                       goto done;
                if(flag&SH_SIGIGNORE)
                {
                        if(shp->subshell)
                                shp->ignsig = sig;
-                       return;
+                       goto done;
                }
                if(flag&SH_SIGDONE)
                {
@@ -161,7 +162,7 @@
                                /* check for TERM signal between fork/exec */
                                if(sig==SIGTERM && job.in_critical)
                                        shp->trapnote |= SH_SIGTERM;
-                               return;
+                               goto done;
                        }
                        shp->lastsig = sig;
                        sigrelease(sig);
@@ -194,7 +195,7 @@
                                        dp->exceptf = malloc_done;
                        }
 #endif
-                       return;
+                       goto done;
                }
        }
        errno = 0;
@@ -224,7 +225,7 @@
                        {
                                sigrelease(sig);
                                sh_exit(shp,SH_EXITSIG);
-                               return;
+                               goto done;
                        }
                }
 #endif /* SIGTSTP */
@@ -232,7 +233,7 @@
        if(shp->bltinfun)
                action = notify_builtin(shp,sig);
        if(action>0)
-               return;
+               goto done;
        shp->trapnote |= flag;
 #ifdef AST_SERIAL_RESTART
        if(flag&(SH_SIGSET|SH_SIGTRAP))
@@ -243,10 +244,12 @@
        if(pp->mode==SH_JMPCMD && sh_isstate(shp,SH_STOPOK))
        {
                if(action<0)
-                       return;
+                       goto done;
                sigrelease(sig);
                sh_exit(shp,SH_EXITSIG);
        }
+done:
+       errno = saved_errno;
 }
 
 /*
diff -r -u build_i386_64bit_debug/src/cmd/ksh93/sh/jobs.c 
build_sigerrno/src/cmd/ksh93/sh/jobs.c
--- src/cmd/ksh93/sh/jobs.c     2013-10-04 17:25:25.000000000 +0200
+++ src/cmd/ksh93/sh/jobs.c     2014-01-23 22:05:24.830307582 +0100
@@ -367,6 +367,8 @@
 static void job_waitsafe(int sig)
 #endif
 {
+       int saved_errno = errno; /* many platforms do not save/restore errno 
for signal handlers */
+
        if(job.in_critical || vmbusy())
        {
                job.savesig = sig;
@@ -374,6 +376,8 @@
        }
        else
                job_reap(sig);
+               
+       errno = saved_errno;
 }
 
 /*
_______________________________________________
ast-developers mailing list
ast-developers@lists.research.att.com
http://lists.research.att.com/mailman/listinfo/ast-developers

Reply via email to