1 // Copyright 2018 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 //go:build freebsd && 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 // os_freebsd.go.  This definition — and its conversion to and from struct
17 // sigaction — are specific to freebsd/amd64.
18 typedef struct {
19         uint32_t __bits[_SIG_WORDS];
20 } go_sigset_t;
21 typedef struct {
22 	uintptr_t handler;
23 	int32_t flags;
24 	go_sigset_t mask;
25 } go_sigaction_t;
26 
27 int32_t
x_cgo_sigaction(intptr_t signum,const go_sigaction_t * goact,go_sigaction_t * oldgoact)28 x_cgo_sigaction(intptr_t signum, const go_sigaction_t *goact, go_sigaction_t *oldgoact) {
29 	int32_t ret;
30 	struct sigaction act;
31 	struct sigaction oldact;
32 	size_t i;
33 
34 	_cgo_tsan_acquire();
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.__bits[i/32] & ((uint32_t)(1)<<(i&31))) {
48 				sigaddset(&act.sa_mask, i+1);
49 			}
50 		}
51 		act.sa_flags = goact->flags;
52 	}
53 
54 	ret = sigaction(signum, goact ? &act : NULL, oldgoact ? &oldact : NULL);
55 	if (ret == -1) {
56 		// runtime.sigaction expects _cgo_sigaction to return errno on error.
57 		_cgo_tsan_release();
58 		return errno;
59 	}
60 
61 	if (oldgoact) {
62 		if (oldact.sa_flags & SA_SIGINFO) {
63 			oldgoact->handler = (uintptr_t)(oldact.sa_sigaction);
64 		} else {
65 			oldgoact->handler = (uintptr_t)(oldact.sa_handler);
66 		}
67 		for (i = 0 ; i < _SIG_WORDS; i++) {
68 			oldgoact->mask.__bits[i] = 0;
69 		}
70 		for (i = 0; i < 8 * sizeof(oldgoact->mask); i++) {
71 			if (sigismember(&oldact.sa_mask, i+1) == 1) {
72 				oldgoact->mask.__bits[i/32] |= (uint32_t)(1)<<(i&31);
73 			}
74 		}
75 		oldgoact->flags = oldact.sa_flags;
76 	}
77 
78 	_cgo_tsan_release();
79 	return ret;
80 }
81