...

Text file src/cmd/cgo/internal/testcarchive/testdata/main3.c

Documentation: cmd/cgo/internal/testcarchive/testdata

     1// Copyright 2015 The Go Authors. All rights reserved.
     2// Use of this source code is governed by a BSD-style
     3// license that can be found in the LICENSE file.
     4
     5// Test os/signal.Notify and os/signal.Reset.
     6// This is a lot like ../testcshared/main5.c.
     7
     8#include <signal.h>
     9#include <stdio.h>
    10#include <stdlib.h>
    11#include <string.h>
    12#include <time.h>
    13#include <sched.h>
    14#include <unistd.h>
    15#include <pthread.h>
    16
    17#include "libgo3.h"
    18
    19static void die(const char* msg) {
    20	perror(msg);
    21	exit(EXIT_FAILURE);
    22}
    23
    24static volatile sig_atomic_t sigioSeen;
    25
    26static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
    27	sigioSeen = 1;
    28}
    29
    30// Set up the SIGPIPE signal handler in a high priority constructor, so
    31// that it is installed before the Go code starts.
    32
    33static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
    34	const char *s = "unexpected SIGPIPE\n";
    35	write(2, s, strlen(s));
    36	exit(EXIT_FAILURE);
    37}
    38
    39static void init(void) __attribute__ ((constructor (200)));
    40
    41static void init() {
    42    struct sigaction sa;
    43
    44	memset(&sa, 0, sizeof sa);
    45	sa.sa_sigaction = pipeHandler;
    46	if (sigemptyset(&sa.sa_mask) < 0) {
    47		die("sigemptyset");
    48	}
    49	sa.sa_flags = SA_SIGINFO;
    50	if (sigaction(SIGPIPE, &sa, NULL) < 0) {
    51		die("sigaction");
    52	}
    53}
    54
    55static void *provokeSIGPIPE(void *arg) {
    56	ProvokeSIGPIPE();
    57	return NULL;
    58}
    59
    60int main(int argc, char** argv) {
    61	int verbose;
    62	struct sigaction sa;
    63	int i;
    64	struct timespec ts;
    65	int res;
    66	pthread_t tid;
    67
    68	verbose = argc > 2;
    69	setvbuf(stdout, NULL, _IONBF, 0);
    70
    71	if (verbose) {
    72		printf("raising SIGPIPE\n");
    73	}
    74
    75	// Test that the Go runtime handles SIGPIPE, even if we installed
    76	// a non-default SIGPIPE handler before the runtime initializes.
    77	ProvokeSIGPIPE();
    78
    79	// Test that SIGPIPE on a non-main thread is also handled by Go.
    80	res = pthread_create(&tid, NULL, provokeSIGPIPE, NULL);
    81	if (res != 0) {
    82		fprintf(stderr, "pthread_create: %s\n", strerror(res));
    83		exit(EXIT_FAILURE);
    84	}
    85
    86	res = pthread_join(tid, NULL);
    87	if (res != 0) {
    88		fprintf(stderr, "pthread_join: %s\n", strerror(res));
    89		exit(EXIT_FAILURE);
    90	}
    91
    92	if (verbose) {
    93		printf("calling sigaction\n");
    94	}
    95
    96	memset(&sa, 0, sizeof sa);
    97	sa.sa_sigaction = ioHandler;
    98	if (sigemptyset(&sa.sa_mask) < 0) {
    99		die("sigemptyset");
   100	}
   101	sa.sa_flags = SA_SIGINFO;
   102	if (sigaction(SIGIO, &sa, NULL) < 0) {
   103		die("sigaction");
   104	}
   105
   106	// At this point there should not be a Go signal handler
   107	// installed for SIGIO.
   108
   109	if (verbose) {
   110		printf("raising SIGIO\n");
   111	}
   112
   113	if (raise(SIGIO) < 0) {
   114		die("raise");
   115	}
   116
   117	if (verbose) {
   118		printf("waiting for sigioSeen\n");
   119	}
   120
   121	// Wait until the signal has been delivered.
   122	i = 0;
   123	while (!sigioSeen) {
   124		ts.tv_sec = 0;
   125		ts.tv_nsec = 1000000;
   126		nanosleep(&ts, NULL);
   127		i++;
   128		if (i > 5000) {
   129			fprintf(stderr, "looping too long waiting for signal\n");
   130			exit(EXIT_FAILURE);
   131		}
   132	}
   133
   134	sigioSeen = 0;
   135
   136	// Tell the Go code to catch SIGIO.
   137
   138	if (verbose) {
   139		printf("calling CatchSIGIO\n");
   140	}
   141
   142	CatchSIGIO();
   143
   144	if (verbose) {
   145		printf("raising SIGIO\n");
   146	}
   147
   148	if (raise(SIGIO) < 0) {
   149		die("raise");
   150	}
   151
   152	if (verbose) {
   153		printf("calling SawSIGIO\n");
   154	}
   155
   156	if (!SawSIGIO()) {
   157		fprintf(stderr, "Go handler did not see SIGIO\n");
   158		exit(EXIT_FAILURE);
   159	}
   160
   161	if (sigioSeen != 0) {
   162		fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
   163		exit(EXIT_FAILURE);
   164	}
   165
   166	// Tell the Go code to stop catching SIGIO.
   167
   168	if (verbose) {
   169		printf("calling ResetSIGIO\n");
   170	}
   171
   172	ResetSIGIO();
   173
   174	if (verbose) {
   175		printf("raising SIGIO\n");
   176	}
   177
   178	if (raise(SIGIO) < 0) {
   179		die("raise");
   180	}
   181
   182	if (verbose) {
   183		printf("calling SawSIGIO\n");
   184	}
   185
   186	if (SawSIGIO()) {
   187		fprintf(stderr, "Go handler saw SIGIO after Reset\n");
   188		exit(EXIT_FAILURE);
   189	}
   190
   191	if (verbose) {
   192		printf("waiting for sigioSeen\n");
   193	}
   194
   195	// Wait until the signal has been delivered.
   196	i = 0;
   197	while (!sigioSeen) {
   198		ts.tv_sec = 0;
   199		ts.tv_nsec = 1000000;
   200		nanosleep(&ts, NULL);
   201		i++;
   202		if (i > 5000) {
   203			fprintf(stderr, "looping too long waiting for signal\n");
   204			exit(EXIT_FAILURE);
   205		}
   206	}
   207
   208	printf("PASS\n");
   209	return 0;
   210}

View as plain text