...

Text file src/cmd/cgo/internal/testcshared/testdata/main5.c

Documentation: cmd/cgo/internal/testcshared/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 that a signal handler works in non-Go code when using
     6// os/signal.Notify.
     7// This is a lot like ../testcarchive/main3.c.
     8
     9#include <signal.h>
    10#include <stdbool.h>
    11#include <stdio.h>
    12#include <stdlib.h>
    13#include <string.h>
    14#include <time.h>
    15#include <sched.h>
    16#include <dlfcn.h>
    17
    18static void die(const char* msg) {
    19	perror(msg);
    20	exit(EXIT_FAILURE);
    21}
    22
    23static volatile sig_atomic_t sigioSeen;
    24
    25static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
    26	sigioSeen = 1;
    27}
    28
    29int main(int argc, char** argv) {
    30	int verbose;
    31	struct sigaction sa;
    32	void* handle;
    33	void (*catchSIGIO)(void);
    34	void (*resetSIGIO)(void);
    35	void (*awaitSIGIO)();
    36	bool (*sawSIGIO)();
    37	int i;
    38	struct timespec ts;
    39
    40	verbose = argc > 2;
    41	setvbuf(stdout, NULL, _IONBF, 0);
    42
    43	if (verbose) {
    44		fprintf(stderr, "calling sigaction\n");
    45	}
    46
    47	memset(&sa, 0, sizeof sa);
    48	sa.sa_sigaction = ioHandler;
    49	if (sigemptyset(&sa.sa_mask) < 0) {
    50		die("sigemptyset");
    51	}
    52	sa.sa_flags = SA_SIGINFO;
    53	if (sigaction(SIGIO, &sa, NULL) < 0) {
    54		die("sigaction");
    55	}
    56
    57	if (verbose) {
    58		fprintf(stderr, "calling dlopen\n");
    59	}
    60
    61	handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
    62	if (handle == NULL) {
    63		fprintf(stderr, "%s\n", dlerror());
    64		exit(EXIT_FAILURE);
    65	}
    66
    67	// At this point there should not be a Go signal handler
    68	// installed for SIGIO.
    69
    70	if (verbose) {
    71		fprintf(stderr, "raising SIGIO\n");
    72	}
    73
    74	if (raise(SIGIO) < 0) {
    75		die("raise");
    76	}
    77
    78	if (verbose) {
    79		fprintf(stderr, "waiting for sigioSeen\n");
    80	}
    81
    82	// Wait until the signal has been delivered.
    83	i = 0;
    84	while (!sigioSeen) {
    85		ts.tv_sec = 0;
    86		ts.tv_nsec = 1000000;
    87		nanosleep(&ts, NULL);
    88		i++;
    89		if (i > 5000) {
    90			fprintf(stderr, "looping too long waiting for signal\n");
    91			exit(EXIT_FAILURE);
    92		}
    93	}
    94
    95	sigioSeen = 0;
    96
    97	// Tell the Go code to catch SIGIO.
    98
    99	if (verbose) {
   100		fprintf(stderr, "calling dlsym\n");
   101	}
   102
   103	catchSIGIO = (void(*)(void))dlsym(handle, "CatchSIGIO");
   104	if (catchSIGIO == NULL) {
   105		fprintf(stderr, "%s\n", dlerror());
   106		exit(EXIT_FAILURE);
   107	}
   108
   109	if (verbose) {
   110		fprintf(stderr, "calling CatchSIGIO\n");
   111	}
   112
   113	catchSIGIO();
   114
   115	if (verbose) {
   116		fprintf(stderr, "raising SIGIO\n");
   117	}
   118
   119	if (raise(SIGIO) < 0) {
   120		die("raise");
   121	}
   122
   123	if (verbose) {
   124		fprintf(stderr, "calling dlsym\n");
   125	}
   126
   127	// Check that the Go code saw SIGIO.
   128	awaitSIGIO = (void (*)(void))dlsym(handle, "AwaitSIGIO");
   129	if (awaitSIGIO == NULL) {
   130		fprintf(stderr, "%s\n", dlerror());
   131		exit(EXIT_FAILURE);
   132	}
   133
   134	if (verbose) {
   135		fprintf(stderr, "calling AwaitSIGIO\n");
   136	}
   137
   138	awaitSIGIO();
   139
   140	if (sigioSeen != 0) {
   141		fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
   142		exit(EXIT_FAILURE);
   143	}
   144
   145	// Tell the Go code to stop catching SIGIO.
   146
   147	if (verbose) {
   148		fprintf(stderr, "calling dlsym\n");
   149	}
   150
   151	resetSIGIO = (void (*)(void))dlsym(handle, "ResetSIGIO");
   152	if (resetSIGIO == NULL) {
   153		fprintf(stderr, "%s\n", dlerror());
   154		exit(EXIT_FAILURE);
   155	}
   156
   157	if (verbose) {
   158		fprintf(stderr, "calling ResetSIGIO\n");
   159	}
   160
   161	resetSIGIO();
   162
   163	sawSIGIO = (bool (*)(void))dlsym(handle, "SawSIGIO");
   164	if (sawSIGIO == NULL) {
   165		fprintf(stderr, "%s\n", dlerror());
   166		exit(EXIT_FAILURE);
   167	}
   168
   169	if (verbose) {
   170		fprintf(stderr, "raising SIGIO\n");
   171	}
   172
   173	if (raise(SIGIO) < 0) {
   174		die("raise");
   175	}
   176
   177	if (verbose) {
   178		fprintf(stderr, "calling SawSIGIO\n");
   179	}
   180
   181	if (sawSIGIO()) {
   182		fprintf(stderr, "Go handler saw SIGIO after Reset\n");
   183		exit(EXIT_FAILURE);
   184	}
   185
   186	if (verbose) {
   187		fprintf(stderr, "waiting for sigioSeen\n");
   188	}
   189
   190	// Wait until the signal has been delivered.
   191	i = 0;
   192	while (!sigioSeen) {
   193		ts.tv_sec = 0;
   194		ts.tv_nsec = 1000000;
   195		nanosleep(&ts, NULL);
   196		i++;
   197		if (i > 5000) {
   198			fprintf(stderr, "looping too long waiting for signal\n");
   199			exit(EXIT_FAILURE);
   200		}
   201	}
   202
   203	printf("PASS\n");
   204	return 0;
   205}

View as plain text