mirror of
https://github.com/golang/go
synced 2024-11-24 08:30:15 -07:00
e57350f4c0
There are a few problems from change 35494, discovered during testing of change 37852. 1. I was confused about the usage of n.key in the sema variant, so we were looping on the wrong condition. The error was not caught by the TryBots (presumably due to missing TSAN coverage in the BSD and darwin builders?). 2. The sysmon goroutine sometimes skips notetsleep entirely, using direct usleep syscalls instead. In that case, we were not calling _cgo_yield, leading to missed signals under TSAN. 3. Some notetsleep calls have long finite timeouts. They should be broken up into smaller chunks with a yield at the end of each chunk. updates #18717 Change-Id: I91175af5dea3857deebc686f51a8a40f9d690bcc Reviewed-on: https://go-review.googlesource.com/37867 Run-TryBot: Bryan Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
56 lines
1.2 KiB
Go
56 lines
1.2 KiB
Go
// Copyright 2017 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
// This program hung when run under the C/C++ ThreadSanitizer. TSAN defers
|
|
// asynchronous signals until the signaled thread calls into libc. The runtime's
|
|
// sysmon goroutine idles itself using direct usleep syscalls, so it could
|
|
// run for an arbitrarily long time without triggering the libc interceptors.
|
|
// See https://golang.org/issue/18717.
|
|
|
|
import (
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
)
|
|
|
|
/*
|
|
#cgo CFLAGS: -g -fsanitize=thread
|
|
#cgo LDFLAGS: -g -fsanitize=thread
|
|
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static void raise_usr2(int signo) {
|
|
raise(SIGUSR2);
|
|
}
|
|
|
|
static void register_handler(int signo) {
|
|
struct sigaction sa;
|
|
memset(&sa, 0, sizeof(sa));
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_flags = SA_ONSTACK;
|
|
sa.sa_handler = raise_usr2;
|
|
|
|
if (sigaction(SIGUSR1, &sa, NULL) != 0) {
|
|
perror("failed to register SIGUSR1 handler");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
func main() {
|
|
ch := make(chan os.Signal)
|
|
signal.Notify(ch, syscall.SIGUSR2)
|
|
|
|
C.register_handler(C.int(syscall.SIGUSR1))
|
|
syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
|
|
|
|
<-ch
|
|
}
|