I have isolated a bug in bash 3.2 which doesn't appear in later
versions of bash I have tried; now I am trying to figure out when
where the bug got fixed so I can make an upgrade plan. I am using SLES
11 SP2.

To reproduce the issue do the following.
* Block SIGPIPE in the current process.
* From the current process, start bash interactively. (The new bash
process also has SIGPIPE blocked.)
* In the latter bash process, run a test program. (The new
test-program process also has SIGPIPE blocked.)

The latter process sees a pending SIGPIPE supposedly sent by itself.
If it unblocks SIGPIPE then it receives this signal immediately.

If the test program is started in various unusual ways such as the
following then it does NOT receive SIGPIPE:

    bash -c '{ test ; }'
    bash -c ': ; test'
    bash -c 'test ; :'
    ( { test ; } )
    ( test ; : )
    echo test | bash -s

whereas it DOES receive SIGPIPE if it as started as follows.

    bash -c test
    test
    ( test )
    ( test ; )
    { test ; }

I have searched in the mailing list archives and looked in the bash
docs but haven't found a clue as to where this bug was fixed. Does
this ring a bell with anyone or is this most likely a distro-specific
bug?

Info:

$ bash --version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)
> rpm -q -a|grep bash
bash-3.2-147.9.13
$ cat /etc/issue
Welcome to SUSE Linux Enterprise Server 11 SP2  (x86_64) - Kernel \r (\l).

I attach the test program I use.
-- 
Thomas Hood
RAAF Technology bv
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

static void sigactor(int signum, siginfo_t *si, void *ctx) {
	 printf("Caught signal %d sent by process %d\n", signum, si->si_pid);
}

int main()
{
	sigset_t sigmask;
	struct sigaction act;

	act.sa_sigaction = sigactor;
	act.sa_flags = SA_RESTART | SA_SIGINFO;

	printf("Running with PID %d\n", getpid());

	printf("Will retrieve existing signal mask\n");
	if (sigprocmask(SIG_SETMASK, NULL, &sigmask)) {
		printf("Failed to retrieve existing signal mask\n");
		return 1;
	}
	if (sigismember (&sigmask, SIGPIPE)) {
		printf("SIGPIPE is blocked\n");
	} else {
		printf("SIGPIPE is not blocked\n");
	}

	printf("Will check for signals pending\n");
	if (sigpending(&sigmask)) {
		printf("Failed to check for signals pending\n");
		return 1;
	}
	if (sigismember (&sigmask, SIGPIPE)) {
		printf("SIGPIPE is pending\n");
	} else {
		printf("SIGPIPE is not pending\n");
	}

	printf("Will install signal handler\n");
	if (sigaction(SIGPIPE, &act, NULL) || sigaction(SIGHUP, &act, NULL) || sigaction(SIGTERM, &act, NULL)) {
		printf("Failed to install signal handler\n");
		return 1;
	}

	//printf("Will sleep\n");
	//sleep(30);

	sigemptyset(&sigmask);
	sigaddset(&sigmask, SIGPIPE);

	printf("Will unblock signal\n");
	if (sigprocmask(SIG_UNBLOCK, &sigmask, NULL)) {
		printf("Error unblocking signal\n");
		return 1;
	}

	printf("Will exit\n");
	return 0;
}

Reply via email to