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

View as plain text