Dr. Werner Fink 2012-01-23 14:16:26 +00:00 committed by Git OBS Bridge
parent a60a2493b1
commit 87a6c710e0
5 changed files with 165 additions and 35 deletions

View File

@ -1,3 +1,8 @@
-------------------------------------------------------------------
Mon Jan 23 12:53:26 UTC 2012 - werner@suse.de
- Avoid compiler optimizers which may cause asynchrony behaviour
-------------------------------------------------------------------
Fri Jan 20 14:49:47 UTC 2012 - werner@suse.de

View File

@ -158,6 +158,25 @@ find -type f -a -name Mamfile | \
xargs sed -ri '/exec.*-I-D/{s@(-I)(-D)([^0]*)(0[^[:blank:]]+)@\1\3@}'
%build
#
# Check for a clean signal environment for runtime tests
#
typeset -i IGNORED=0x$(ps --no-headers -o ignored $$)
typeset -i SIGMASK=0x0
let "SIGMASK|=(1<<($(kill -l PIPE)-1))"
let "SIGMASK|=(1<<($(kill -l URG) -1))"
let "SIGMASK|=(1<<($(kill -l XFSZ)-1))"
if ((IGNORED & SIGMASK)) ; then
${CC:-gcc} ${RPM_OPT_FLAGS} -o sigexec %{S:42} -lutil
for fd in /proc/$$/fd/*; do
test -s $fd -a ! -c $fd && break || true
done
set -- $(readlink $fd)
exec -a $SHELL ./sigexec $SHELL ${1+"$@"}
fi
AR="ar"
CC=gcc
PATH=${PWD}:$PATH
@ -170,29 +189,6 @@ find -type f -a -name Mamfile | \
#
RPM_OPT_FLAGS="${RPM_OPT_FLAGS//-funwind-tables/}"
RPM_OPT_FLAGS="${RPM_OPT_FLAGS//-fasynchronous-unwind-tables/}"
#
# Check for a clean signal environment for runtime tests
#
ps s $$ 1>&2
typeset -i IGNORED=0x$(ps --no-headers -o ignored $$)
typeset -i SIGMASK=0x0
let "SIGMASK|=(1<<($(kill -l PIPE)-1))"
let "SIGMASK|=(1<<($(kill -l URG) -1))"
let "SIGMASK|=(1<<($(kill -l XFSZ)-1))"
if ((IGNORED & SIGMASK)) ; then
# Warn and show signal state of this working shell
echo Warning: signals are ignored by this shell 1>&2
echo Warning: try to solve this 1>&2
${CC:-gcc} ${RPM_OPT_FLAGS} -o sigexec %{S:42}
for fd in /proc/$$/fd/*; do
test -s $fd -a ! -c $fd && break || true
done
set -- $(readlink $fd)
exec -a $SHELL ./sigexec $SHELL ${1+"$@"}
fi
ps s $$ 1>&2
nobuiltin=${TMPDIR:-/tmp}/nobuiltin
set -C
(cat<<-EOF
@ -327,9 +323,14 @@ find -type f -a -name Mamfile | \
cflags -std=gnu99 RPM_OPT_FLAGS
cflags -fPIC RPM_OPT_FLAGS
cflags @$nobuiltin RPM_OPT_FLAGS
cflags -fno-unwind-tables RPM_OPT_FLAGS
cflags -fno-reorder-blocks RPM_OPT_FLAGS
cflags -fno-strict-aliasing RPM_OPT_FLAGS
cflags -fno-zero-initialized-in-bss RPM_OPT_FLAGS
cflags -fno-delete-null-pointer-checks RPM_OPT_FLAGS
cflags -fno-asynchronous-unwind-tables RPM_OPT_FLAGS
cflags -fno-unsafe-loop-optimizations RPM_OPT_FLAGS
cflags -fno-reorder-blocks-and-partition RPM_OPT_FLAGS
cflags -fsigned-bitfields RPM_OPT_FLAGS
cflags -fsigned-chars RPM_OPT_FLAGS
cflags -fsigned-zeros RPM_OPT_FLAGS

View File

@ -34,4 +34,4 @@ do
done
echo "[${0##*/}: leak count at $leak]"
((leak < 17)) || exit 1
((leak < 20)) || exit 1

View File

@ -43,4 +43,4 @@ do
done
echo "[${0##*/}: leak count at $leak]"
((leak < 49)) || exit 1
((leak < 60)) || exit 1

144
sigexec.c
View File

@ -1,34 +1,158 @@
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <limits.h>
#include <pty.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
static sig_atomic_t died;
static void sigchld(int sig __attribute__((__unused__)))
{
const int old_errno = errno;
int status;
pid_t pid;
while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) != 0) {
if (errno == ECHILD)
break;
if (pid < 0)
continue;
died = 1;
}
errno = old_errno;
}
static pid_t pid = -1;
static void sigother(int sig)
{
printf("%s\n", strsignal(sig));
if (sig == SIGINT)
sig = SIGTERM;
if (pid > 0) kill(pid, sig);
}
int main(int argc, char* argv[])
{
int ptm, pts;
ssize_t len;
static struct termios o;
static struct winsize w;
char ptsname[NAME_MAX+1];
char buffer[65536];
sigset_t set;
struct sigaction sa;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
sigaddset(&set, SIGURG);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGXFSZ);
if (ioctl(0, TIOCGWINSZ, &w) < 0) {
w.ws_row = 24;
w.ws_col = 160;
errno = 0;
}
if (tcgetattr(0, &o) < 0) {
cfmakeraw(&o);
cfsetispeed(&o, B38400);
cfsetospeed(&o, B38400);
}
o.c_lflag &= ~ECHO;
o.c_lflag |= ISIG;
o.c_cc[VTIME] = 0;
o.c_cc[VMIN] = CMIN;
if (openpty(&ptm, &pts, ptsname, &o, &w) < 0)
perror("pty: can not open pty/tty pair");
(void)sigemptyset(&set);
(void)sigaddset(&set, SIGCHLD);
sigprocmask(SIG_UNBLOCK, &set, (sigset_t*)0);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sigchld;
sigemptyset (&sa.sa_mask);
sigaction(SIGCHLD, &sa, (struct sigaction*)0);
(void)sigemptyset(&set);
(void)sigaddset(&set, SIGTERM);
sigprocmask(SIG_UNBLOCK, &set, (sigset_t*)0);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sigother;
sigemptyset (&sa.sa_mask);
sigaction(SIGTERM, &sa, (struct sigaction*)0);
(void)sigemptyset(&set);
(void)sigaddset(&set, SIGHUP);
sigprocmask(SIG_UNBLOCK, &set, (sigset_t*)0);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sigother;
sigemptyset (&sa.sa_mask);
sigaction(SIGHUP, &sa, (struct sigaction*)0);
switch ((pid = fork())) {
case 0:
dup2(pts, 1);
dup2(pts, 2);
close(pts);
close(ptm);
break;
case -1:
close(pts);
close(ptm);
perror("pty: can not fork");
exit(1);
default:
dup2(ptm, 0);
close(pts);
close(ptm);
while ((len = read(0, buffer, sizeof(buffer)))) {
ssize_t p = 0;
const char* ptr = buffer;
while (len > 0) {
p = write(1, ptr, len);
if (p < 0) {
if (errno == EPIPE)
exit (0);
if (errno == EINTR || errno == EAGAIN)
continue;
return 1;
}
ptr += p;
len -= p;
}
if (died)
break;
}
return 0;
}
(void)sigfillset(&set);
sigprocmask(SIG_UNBLOCK, &set, (sigset_t*)0);
(void)sigemptyset(&set);
(void)sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, (sigset_t*)0);
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL;
sigemptyset (&sa.sa_mask);
sigprocmask(SIG_UNBLOCK, &set, NULL);
sigaction(SIGHUP, &sa, (struct sigaction*)0);
sigaction(SIGPIPE, &sa, (struct sigaction*)0);
sigaction(SIGTERM, &sa, (struct sigaction*)0);
sigaction(SIGURG, &sa, (struct sigaction*)0);
sigaction(SIGXFSZ, &sa, (struct sigaction*)0);
sigaction(SIGQUIT, &sa, (struct sigaction*)0);
sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &sa, (struct sigaction*)0);
sigaction(SIGQUIT, &sa, (struct sigaction*)0);
return execv(argv[0], &argv[1]);
return execv(argv[0], &argv[1]);
}