Web lists-archives.com

Bug: Synchronous signals broken on Cygwin 64




Hello mailing list,

I noticed that synchronous signals (e.g., SIGSEGV, SIGFPE) appear to be
broken on 64-bit Cygwin systems. I could not find additional information
on the mailing list. If this is not already a known problem, you'll find
some analysis below.


I use Cygwin DLL 2.10 with all packages up-to-date. My test system runs
Windows 7.


The expected behavior is that an installed signal handler runs exactly
once for a signal and the OS terminates the program if the handler
returns. This works on 32-bit Cygwin. From my observation, Cygwin 64
differs in the follow ways:

1) Generating a synchronous signal on the main thread, makes the signal
handler enter an endless loop. The attached test 'syncsig.c' illustrates
this.

2) Generating a synchronous signal on an additional POSIX thread ignores
the installed signal handler entirely. The handler does not run and the
program gets terminated immediately. The attached test 'syncsig_mt.c'
illustrates this.


As mentioned, both cases work correctly on 32-bit installations. I
cannot point to the exact location of the problem, but it appears that
the Cygwin exception-handler code is not set up by 64-bit code.

In case 2) I can see the Windows function KiUserExceptionDispatcher()
being executed for the synchronous signal on the affected thread. This
should lead to a call to the Cygwin exception handler. It does for
32-bit, but not for 64-bit code.

From what I've seen, the exception handler is installed in the c'tor
exception::exception(). [exception.cc:138] The only invocation I found
was in SetThreadName(). [miscfuncs.cc:951] This set-up code is 32-bit-only.


BTW, is there a bug tracker for Cygwin? I'd open a bug report there, or
add the information to an existing one.


Best regards
Thomas


[exception.cc:138]
https://cygwin.com/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/exception.h;h=ffff7464ba11b5526fcf9d13e32334912a30a3b0;hb=4c73ad6b20378e4b74355fcdb2005f2aac489c9f#l138

[miscfuncs.cc:951]
https://cygwin.com/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/miscfuncs.cc;h=3ad658739ad9e85868ca74ce2e86aa6ddbdbfb37;hb=4c73ad6b20378e4b74355fcdb2005f2aac489c9f#l951

-- 
Implement thread-safe and fault-tolerant software in C: visit picotm.org
--
GnuPG:          http://tdz.users.sourceforge.net/tdz.asc
Fingerprint:    16FF F599 82F8 E5AA 18C6 5220 D9DA D7D4 4EF1 DF08
Website:        transactionblog.org
/*
 * This test program works on 32-bit and 64-bit Cygwin. On 32-bit 
 * systems, the signal handler runs *exactly* once, which is the correct
 * behaviour. On 64-bit systems, the exception code enters an endless 
 * loop and the signal handler runs over and over.
 *
 * Compile with
 *
 * 	gcc -Wall -O0 -osyncsig ./syncsig.c
 *
 * Run with
 *
 * 	./syncsig
 *
 * Expected Result
 *
 * 	Program prints "signal handler running" once
 *
 * Actual Result
 *
 * 	On 64-bit systems, the handler runs in an endless loop
 * */

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static void
signal_handler(int signum, siginfo_t* info, void* ucontext)
{
	fprintf(stderr, "signal handler running\n"); // unsafe in real code!
}

int
main(int argc, char* argv[])
{
	struct sigaction act = {
		.sa_sigaction = signal_handler,
		.sa_flags = SA_SIGINFO,
	};
	sigemptyset(&act.sa_mask);

	sigaction(SIGFPE, &act, NULL);

	/* Trigger Windows Exception for division by zero */
	argc /= !argc;

	fprintf(stderr, "no exception generated\n");

	return EXIT_SUCCESS;
}
/*
 * This test program works on 32-bit Cygwin, but fails on 64-bit systems.
 * Running a signal handler for SIGFPE on the created POSIX thread does
 * not work.
 *
 * Compile with
 *
 * 	gcc -Wall -O0 -pthread -osyncsig_mt ./syncsig_mt.c
 *
 * Run with
 *
 * 	./syncsig_mt
 *
 * Expected Result
 *
 * 	Program prints "signal handler running"
 *
 * Actual Result
 *
 * 	No output on 64-bit systems, signal handler does not run
 * */

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static void
signal_handler(int signum, siginfo_t* info, void* ucontext)
{
	fprintf(stderr, "signal handler running\n"); // unsafe in real code!
}

static void*
thread_start(void* arg)
{
	int argc = *(int*)arg;

	/* Trigger Windows Exception for division by zero */
	argc /= !argc;

	fprintf(stderr, "no exception generated\n");

	return NULL;
}

int
main(int argc, char* argv[])
{
	struct sigaction act = {
		.sa_sigaction = signal_handler,
		.sa_flags = SA_SIGINFO,
	};
	sigemptyset(&act.sa_mask);

	sigaction(SIGFPE, &act, NULL);

	pthread_t thread;
	pthread_create(&thread, NULL, thread_start, &argc);
	pthread_join(thread, NULL);

	return EXIT_SUCCESS;
}

Attachment: signature.asc
Description: OpenPGP digital signature