github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/runtime/cgo/gcc_sigaction.c (about)

     1  // Copyright 2016 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  // +build linux,amd64
     6  
     7  #include <errno.h>
     8  #include <stddef.h>
     9  #include <stdint.h>
    10  #include <string.h>
    11  #include <signal.h>
    12  
    13  // go_sigaction_t is a C version of the sigactiont struct from
    14  // defs_linux_amd64.go.  This definition — and its conversion to and from struct
    15  // sigaction — are specific to linux/amd64.
    16  typedef struct {
    17  	uintptr_t handler;
    18  	uint64_t flags;
    19  	uintptr_t restorer;
    20  	uint64_t mask;
    21  } go_sigaction_t;
    22  
    23  // SA_RESTORER is part of the kernel interface.
    24  // This is GNU/Linux i386/amd64 specific.
    25  #ifndef SA_RESTORER
    26  #define SA_RESTORER 0x4000000
    27  #endif
    28  
    29  int32_t
    30  x_cgo_sigaction(intptr_t signum, const go_sigaction_t *goact, go_sigaction_t *oldgoact) {
    31  	int32_t ret;
    32  	struct sigaction act;
    33  	struct sigaction oldact;
    34  	int i;
    35  
    36  	memset(&act, 0, sizeof act);
    37  	memset(&oldact, 0, sizeof oldact);
    38  
    39  	if (goact) {
    40  		if (goact->flags & SA_SIGINFO) {
    41  			act.sa_sigaction = (void(*)(int, siginfo_t*, void*))(goact->handler);
    42  		} else {
    43  			act.sa_handler = (void(*)(int))(goact->handler);
    44  		}
    45  		sigemptyset(&act.sa_mask);
    46  		for (i = 0; i < 8 * sizeof(goact->mask); i++) {
    47  			if (goact->mask & ((uint64_t)(1)<<i)) {
    48  				sigaddset(&act.sa_mask, i+1);
    49  			}
    50  		}
    51  		act.sa_flags = goact->flags & ~SA_RESTORER;
    52  	}
    53  
    54  	ret = sigaction(signum, goact ? &act : NULL, oldgoact ? &oldact : NULL);
    55  	if (ret == -1) {
    56  		/* This is what the Go code expects on failure. */
    57  		return errno;
    58  	}
    59  
    60  	if (oldgoact) {
    61  		if (oldact.sa_flags & SA_SIGINFO) {
    62  			oldgoact->handler = (uintptr_t)(oldact.sa_sigaction);
    63  		} else {
    64  			oldgoact->handler = (uintptr_t)(oldact.sa_handler);
    65  		}
    66  		oldgoact->mask = 0;
    67  		for (i = 0; i < 8 * sizeof(oldgoact->mask); i++) {
    68  			if (sigismember(&act.sa_mask, i+1) == 1) {
    69  				oldgoact->mask |= (uint64_t)(1)<<i;
    70  			}
    71  		}
    72  		oldgoact->flags = act.sa_flags;
    73  	}
    74  
    75  	return ret;
    76  }