Text file src/runtime/cgo/gcc_freebsd_sigaction.c

     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
    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  

View as plain text