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