Text file src/runtime/cgo/gcc_sigaction.c

     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  //go:build linux && (amd64 || arm64 || ppc64le)
     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.
    18  typedef 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 Linux i386/amd64 specific.
    27  #ifndef SA_RESTORER
    28  #define SA_RESTORER 0x4000000
    29  #endif
    30  
    31  int32_t
    32  x_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  	size_t 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, (int)(i+1));
    53  			}
    54  		}
    55  		act.sa_flags = (int)(goact->flags & ~(uint64_t)SA_RESTORER);
    56  	}
    57  
    58  	ret = sigaction((int)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, (int)(i+1)) == 1) {
    74  				oldgoact->mask |= (uint64_t)(1)<<i;
    75  			}
    76  		}
    77  		oldgoact->flags = (uint64_t)oldact.sa_flags;
    78  	}
    79  
    80  	_cgo_tsan_release();
    81  	return ret;
    82  }
    83  

View as plain text