Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sqweek authored and ianlancetaylor committed Jan 9, 2014
1 parent d1ba298 commit c4770b9
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
1 change: 1 addition & 0 deletions misc/cgo/test/cgo_linux_test.go
Expand Up @@ -7,3 +7,4 @@ package cgotest
import "testing"

func TestSetgid(t *testing.T) { testSetgid(t) }
func Test6997(t *testing.T) { test6997(t) }
26 changes: 26 additions & 0 deletions misc/cgo/test/issue6997_linux.c
@@ -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);
}
40 changes: 40 additions & 0 deletions misc/cgo/test/issue6997_linux.go
@@ -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")
}
}
2 changes: 1 addition & 1 deletion src/pkg/runtime/signals_linux.h
Expand Up @@ -41,7 +41,7 @@ SigTab runtime·sigtab[] = {
/* 29 */ N, "SIGIO: i/o now possible",
/* 30 */ N, "SIGPWR: power failure restart",
/* 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 */
/* 34 */ N, "signal 34",
/* 35 */ N, "signal 35",
Expand Down

0 comments on commit c4770b9

Please sign in to comment.