public inbox for cygwin-developers@cygwin.com
 help / color / mirror / Atom feed
* Signal delivered while blocked
@ 2021-12-27  4:51 Marco Atzeri
  2021-12-27 23:14 ` David McFarland
  0 siblings, 1 reply; 4+ messages in thread
From: Marco Atzeri @ 2021-12-27  4:51 UTC (permalink / raw)
  To: cygwin-developers

[-- Attachment #1: Type: text/plain, Size: 257 bytes --]

Hi Guys,

Some time ago (2017) a Postgres developer reported a signal issue
not present in older version (2013)

https://sourceware.org/pipermail/cygwin/2017-August/234001.html

For what I can see the issue is still present.


Ideas for debugging ?

Marco


[-- Attachment #2: sigprocmask-exclusion.c --]
[-- Type: text/plain, Size: 3190 bytes --]

/*
 * Demonstrate improper delivery of a blocked signal.
 *
 * This program prints "ERROR: already forbidden" and aborts within one
 * second on this configuration (uname -srvm):
 *   CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18 x86_64
 *
 * It runs indefinitely (>600s) without trouble on these configurations:
 *   CYGWIN_NT-6.0 1.7.27(0.271/5/3) 2013-12-09 11:57 i686
 *   Linux 3.10.0-514.16.1.el7.x86_64 #1 SMP Wed Apr 12 15:04:24 UTC 2017 x86_64 [CentOS 7]
 *   AIX 7100-03-02-1412
 *   SunOS 5.10 Generic_147147-26 sun4u
 */

#include <setjmp.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static sigset_t block, unblock;
static sig_atomic_t sigblocked = 0;	/* Have I blocked signals? */
static char *stack_base;
static sigjmp_buf jmp;

static void
sigforbid(void)
{
	const char errmsg[] = "ERROR: already forbidden\n";

	if (sigprocmask(SIG_SETMASK, &block, NULL) != 0)
		perror("sigprocmask");

	if (sigblocked == 1)
	{
		write(2, errmsg, sizeof(errmsg) - 1);
		abort();
	}
	sigblocked = 1;
}

static void
sigpermit(void)
{
	const char errmsg[] = "ERROR: already permitted\n";

	if (sigblocked == 0)
	{
		write(2, errmsg, sizeof(errmsg) - 1);
		abort();
	}
	sigblocked = 0;

	if (sigprocmask(SIG_SETMASK, &unblock, NULL) != 0)
		perror("sigprocmask");
}

/*
 * Start fresh in main() when the stack gets too deep.  This is not essential
 * to the test, but it allows for long runs without huge RLIMIT_STACK.
 */
static void
clear_stack_if_needed(void)
{
	char stack_position;
	ptrdiff_t stack_usage;

	stack_usage = stack_base - &stack_position;
	if (stack_usage < 0)
		stack_usage = -stack_usage;
	if (stack_usage > 1024 * 1024)
	{
		puts("releasing excess stack");
		sigblocked = 1;
		siglongjmp(jmp, 1);
	}
}

static void
handler(int arg)
{
	sigforbid();
	clear_stack_if_needed();
	/* wait for extra signal to arrive, after 1-2ms */
	usleep(5000);
	sigpermit();
}

int main(int argc, char **argv)
{
	char stack_position;

	/* initial signal mask setup */
	sigemptyset(&unblock);

	sigfillset(&block);
	sigdelset(&block, SIGTRAP);
	sigdelset(&block, SIGABRT);
	sigdelset(&block, SIGILL);
	sigdelset(&block, SIGFPE);
	sigdelset(&block, SIGSEGV);
	sigdelset(&block, SIGBUS);
	sigdelset(&block, SIGSYS);
	sigdelset(&block, SIGCONT);

	sigforbid();

	/* Register signal handlers.  Problem somehow requires two signals. */
	{
		struct sigaction act, oact;

		act.sa_handler = handler;
		sigemptyset(&act.sa_mask);
		act.sa_flags = 0;
		if (sigaction(SIGUSR1, &act, &oact) != 0)
			perror("sigaction");
		if (sigaction(SIGCHLD, &act, &oact) != 0)
			perror("sigaction");
	}

	/* start a child to inundate me with signals */
	{
		pid_t pid, ppid;
		pid = fork();
		switch (pid)
		{
			case -1:
				perror("fork");
				return 1;
			case 0:
				ppid = getppid();
				printf("pid=%d inundating pid=%d with SIGUSR1 and SIGCHLD\n",
					   getpid(), ppid);
				while (kill(ppid, random() % 2 ? SIGUSR1 : SIGCHLD) == 0)
					;
				puts("child done");
				return 0;
		}
	}

	/* loop forever while we receive signals */
	stack_base = &stack_position;
	sigsetjmp(jmp, 1);
	for (;;)
	{
		sigpermit();
		usleep(1000);
		sigforbid();
	}
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-12-28 13:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-27  4:51 Signal delivered while blocked Marco Atzeri
2021-12-27 23:14 ` David McFarland
2021-12-28  2:46   ` Marco Atzeri
2021-12-28 13:41   ` Z. Majeed

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).