(root)/
gcc-13.2.0/
libgo/
misc/
cgo/
testcarchive/
testdata/
main3.c
       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 misc/cgo/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  
      19  static void die(const char* msg) {
      20  	perror(msg);
      21  	exit(EXIT_FAILURE);
      22  }
      23  
      24  static volatile sig_atomic_t sigioSeen;
      25  
      26  static 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  
      33  static 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  
      39  static void init(void) __attribute__ ((constructor (200)));
      40  
      41  static 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  
      55  static void *provokeSIGPIPE(void *arg) {
      56  	ProvokeSIGPIPE();
      57  	return NULL;
      58  }
      59  
      60  int 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  }