Home | History | Annotate | Download | only in cgo
      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 }
     77