+++ /dev/null
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test a C thread that calls sigaltstack and then calls Go code.
-
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <sched.h>
-#include <pthread.h>
-
-#include "libgo4.h"
-
-#ifdef _AIX
-// On AIX, CSIGSTKSZ is too small to handle Go sighandler.
-#define CSIGSTKSZ 0x4000
-#else
-#define CSIGSTKSZ SIGSTKSZ
-#endif
-
-static void die(const char* msg) {
- perror(msg);
- exit(EXIT_FAILURE);
-}
-
-static int ok = 1;
-
-static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
-}
-
-// Set up the SIGIO signal handler in a high priority constructor, so
-// that it is installed before the Go code starts.
-
-static void init(void) __attribute__ ((constructor (200)));
-
-static void init() {
- struct sigaction sa;
-
- memset(&sa, 0, sizeof sa);
- sa.sa_sigaction = ioHandler;
- if (sigemptyset(&sa.sa_mask) < 0) {
- die("sigemptyset");
- }
- sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
- if (sigaction(SIGIO, &sa, NULL) < 0) {
- die("sigaction");
- }
-}
-
-// Test raising SIGIO on a C thread with an alternate signal stack
-// when there is a Go signal handler for SIGIO.
-static void* thread1(void* arg __attribute__ ((unused))) {
- stack_t ss;
- int i;
- stack_t nss;
- struct timespec ts;
-
- // Set up an alternate signal stack for this thread.
- memset(&ss, 0, sizeof ss);
- ss.ss_sp = malloc(CSIGSTKSZ);
- if (ss.ss_sp == NULL) {
- die("malloc");
- }
- ss.ss_flags = 0;
- ss.ss_size = CSIGSTKSZ;
- if (sigaltstack(&ss, NULL) < 0) {
- die("sigaltstack");
- }
-
- // Send ourselves a SIGIO. This will be caught by the Go
- // signal handler which should forward to the C signal
- // handler.
- i = pthread_kill(pthread_self(), SIGIO);
- if (i != 0) {
- fprintf(stderr, "pthread_kill: %s\n", strerror(i));
- exit(EXIT_FAILURE);
- }
-
- // Wait until the signal has been delivered.
- i = 0;
- while (SIGIOCount() == 0) {
- ts.tv_sec = 0;
- ts.tv_nsec = 1000000;
- nanosleep(&ts, NULL);
- i++;
- if (i > 5000) {
- fprintf(stderr, "looping too long waiting for signal\n");
- exit(EXIT_FAILURE);
- }
- }
-
- // We should still be on the same signal stack.
- if (sigaltstack(NULL, &nss) < 0) {
- die("sigaltstack check");
- }
- if ((nss.ss_flags & SS_DISABLE) != 0) {
- fprintf(stderr, "sigaltstack disabled on return from Go\n");
- ok = 0;
- } else if (nss.ss_sp != ss.ss_sp) {
- fprintf(stderr, "sigaltstack changed on return from Go\n");
- ok = 0;
- }
-
- return NULL;
-}
-
-// Test calling a Go function to raise SIGIO on a C thread with an
-// alternate signal stack when there is a Go signal handler for SIGIO.
-static void* thread2(void* arg __attribute__ ((unused))) {
- stack_t ss;
- int i;
- int oldcount;
- pthread_t tid;
- struct timespec ts;
- stack_t nss;
-
- // Set up an alternate signal stack for this thread.
- memset(&ss, 0, sizeof ss);
- ss.ss_sp = malloc(CSIGSTKSZ);
- if (ss.ss_sp == NULL) {
- die("malloc");
- }
- ss.ss_flags = 0;
- ss.ss_size = CSIGSTKSZ;
- if (sigaltstack(&ss, NULL) < 0) {
- die("sigaltstack");
- }
-
- oldcount = SIGIOCount();
-
- // Call a Go function that will call a C function to send us a
- // SIGIO.
- tid = pthread_self();
- GoRaiseSIGIO(&tid);
-
- // Wait until the signal has been delivered.
- i = 0;
- while (SIGIOCount() == oldcount) {
- ts.tv_sec = 0;
- ts.tv_nsec = 1000000;
- nanosleep(&ts, NULL);
- i++;
- if (i > 5000) {
- fprintf(stderr, "looping too long waiting for signal\n");
- exit(EXIT_FAILURE);
- }
- }
-
- // We should still be on the same signal stack.
- if (sigaltstack(NULL, &nss) < 0) {
- die("sigaltstack check");
- }
- if ((nss.ss_flags & SS_DISABLE) != 0) {
- fprintf(stderr, "sigaltstack disabled on return from Go\n");
- ok = 0;
- } else if (nss.ss_sp != ss.ss_sp) {
- fprintf(stderr, "sigaltstack changed on return from Go\n");
- ok = 0;
- }
-
- return NULL;
-}
-
-int main(int argc, char **argv) {
- pthread_t tid;
- int i;
-
- // Tell the Go library to start looking for SIGIO.
- GoCatchSIGIO();
-
- i = pthread_create(&tid, NULL, thread1, NULL);
- if (i != 0) {
- fprintf(stderr, "pthread_create: %s\n", strerror(i));
- exit(EXIT_FAILURE);
- }
-
- i = pthread_join(tid, NULL);
- if (i != 0) {
- fprintf(stderr, "pthread_join: %s\n", strerror(i));
- exit(EXIT_FAILURE);
- }
-
- i = pthread_create(&tid, NULL, thread2, NULL);
- if (i != 0) {
- fprintf(stderr, "pthread_create: %s\n", strerror(i));
- exit(EXIT_FAILURE);
- }
-
- i = pthread_join(tid, NULL);
- if (i != 0) {
- fprintf(stderr, "pthread_join: %s\n", strerror(i));
- exit(EXIT_FAILURE);
- }
-
- if (!ok) {
- exit(EXIT_FAILURE);
- }
-
- printf("PASS\n");
- return 0;
-}