mirror of https://github.com/golang/go.git
runtime: co-exist with NPTL's pthread_cancel.
NPTL uses SIGRTMIN (signal 32) to effect thread cancellation. Go's runtime replaces NPTL's signal handler with its own, and ends up aborting if a C library that ends up calling pthread_cancel is used. This patch prevents runtime from replacing NPTL's handler. Fixes #6997. R=golang-codereviews, iant, dvyukov CC=golang-codereviews https://golang.org/cl/47540043
This commit is contained in:
parent
d1ba298ad2
commit
c4770b991b
|
|
@ -7,3 +7,4 @@ package cgotest
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestSetgid(t *testing.T) { testSetgid(t) }
|
func TestSetgid(t *testing.T) { testSetgid(t) }
|
||||||
|
func Test6997(t *testing.T) { test6997(t) }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static pthread_t thread;
|
||||||
|
|
||||||
|
static void* threadfunc(void* dummy) {
|
||||||
|
while(1) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int StartThread() {
|
||||||
|
return pthread_create(&thread, NULL, &threadfunc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CancelThread() {
|
||||||
|
void *r;
|
||||||
|
pthread_cancel(thread);
|
||||||
|
pthread_join(thread, &r);
|
||||||
|
return (r == PTHREAD_CANCELED);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// Test that pthread_cancel works as expected
|
||||||
|
// (NPTL uses SIGRTMIN to implement thread cancellation)
|
||||||
|
// See http://golang.org/issue/6997
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -pthread
|
||||||
|
#cgo LDFLAGS: -pthread
|
||||||
|
extern int StartThread();
|
||||||
|
extern int CancelThread();
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func test6997(t *testing.T) {
|
||||||
|
r := C.StartThread()
|
||||||
|
if r != 0 {
|
||||||
|
t.Error("pthread_create failed")
|
||||||
|
}
|
||||||
|
c := make(chan C.int)
|
||||||
|
go func() {
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
c <- C.CancelThread()
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case r = <-c:
|
||||||
|
if r == 0 {
|
||||||
|
t.Error("pthread finished but wasn't cancelled??")
|
||||||
|
}
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
t.Error("hung in pthread_cancel/pthread_join")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ SigTab runtime·sigtab[] = {
|
||||||
/* 29 */ N, "SIGIO: i/o now possible",
|
/* 29 */ N, "SIGIO: i/o now possible",
|
||||||
/* 30 */ N, "SIGPWR: power failure restart",
|
/* 30 */ N, "SIGPWR: power failure restart",
|
||||||
/* 31 */ N, "SIGSYS: bad system call",
|
/* 31 */ N, "SIGSYS: bad system call",
|
||||||
/* 32 */ N, "signal 32",
|
/* 32 */ 0, "signal 32", /* SIGCANCEL; see issue 6997 */
|
||||||
/* 33 */ 0, "signal 33", /* SIGSETXID; see issue 3871 */
|
/* 33 */ 0, "signal 33", /* SIGSETXID; see issue 3871 */
|
||||||
/* 34 */ N, "signal 34",
|
/* 34 */ N, "signal 34",
|
||||||
/* 35 */ N, "signal 35",
|
/* 35 */ N, "signal 35",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue