runtime: fixes for -buildmode=c-archive

With -buildmode=c-archive, initsig is called before the memory
    allocator has been initialized.  The code was doing a memory
    allocation because of the call to funcPC(sigtramp).  When escape
    analysis is fully implemented, that call should not allocate.  For
    now, finesse the issue by calling a C function to get the C function
    pointer value of sigtramp.
    
    When returning from a call from C to a Go function, a deferred
    function is run to go back to syscall mode.  When the call occurs on a
    non-Go thread, that call sets g to nil, making it impossible to add
    the _defer struct back to the pool.  Just drop it and let the garbage
    collector clean it up.
    
    Reviewed-on: https://go-review.googlesource.com/33675

From-SVN: r242992
This commit is contained in:
Ian Lance Taylor 2016-11-30 02:09:24 +00:00
parent f521b29334
commit fbe9724cc3
5 changed files with 24 additions and 6 deletions

View File

@ -1,4 +1,4 @@
4d8e00e730897cc7e73b1582522ecab031cfcaf2
1d3e0ceee45012a1c3b4ff7f5119a72f90bfcf6a
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -141,6 +141,15 @@ func freedefer(d *_defer) {
if d.special {
return
}
// When C code calls a Go function on a non-Go thread, the
// deferred call to cgocallBackDone will set g to nil.
// Don't crash trying to put d on the free list; just let it
// be garbage collected.
if getg() == nil {
return
}
mp := acquirem()
pp := mp.p.ptr()
if len(pp.deferpool) == cap(pp.deferpool) {

View File

@ -93,7 +93,7 @@ func initsig(preinit bool) {
}
t.flags |= _SigHandling
setsig(i, funcPC(sigtramp), true)
setsig(i, getSigtramp(), true)
}
}
@ -137,7 +137,7 @@ func sigenable(sig uint32) {
if t.flags&_SigHandling == 0 {
t.flags |= _SigHandling
fwdSig[sig] = getsig(int32(sig))
setsig(int32(sig), funcPC(sigtramp), true)
setsig(int32(sig), getSigtramp(), true)
}
}
}
@ -265,7 +265,7 @@ func raisebadsignal(sig int32, c *sigctxt) {
// We may receive another instance of the signal before we
// restore the Go handler, but that is not so bad: we know
// that the Go program has been ignoring the signal.
setsig(sig, funcPC(sigtramp), true)
setsig(sig, getSigtramp(), true)
}
func crash() {

View File

@ -502,8 +502,8 @@ func goexit1()
func schedtrace(bool)
func freezetheworld()
// Signal trampoline, written in C.
func sigtramp()
// Get signal trampoline, written in C.
func getSigtramp() uintptr
// The sa_handler field is generally hidden in a union, so use C accessors.
func getSigactionHandler(*_sigaction) uintptr

View File

@ -140,6 +140,15 @@ sigtramp(int sig, siginfo_t *info, void *context)
#endif // USING_SPLIT_STACK
// C function to return the address of the sigtramp function.
uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp");
uintptr
getSigtramp()
{
return (uintptr)(void*)sigtramp;
}
// C code to manage the sigaction sa_sigaction field, which is
// typically a union and so hard for mksysinfo.sh to handle.