mirror of https://github.com/golang/go.git
runtime/cgo: retry pthread_create on EAGAIN for OpenBSD
For reasons that I do not know, OpenBSD does not call pthread_create directly, but instead looks it up in libpthread.so. That means that we can't use the code used on other systems to retry pthread_create on EAGAIN, since that code simply calls pthread_create. This patch copies that code to an OpenBSD-specific version. Also, check for an EAGAIN failure in the test, as that seems to be the underlying cause of the test failure on several systems including OpenBSD. Fixes #18146. Change-Id: I3bceaa1e03a7eaebc2da19c9cc146b25b59243ef Reviewed-on: https://go-review.googlesource.com/33905 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
a303f05f86
commit
80acfe950f
|
|
@ -18,14 +18,10 @@ import (
|
|||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func test18146(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "openbsd", "dragonfly":
|
||||
t.Skip("skipping on %s; issue 18146", runtime.GOOS)
|
||||
}
|
||||
|
||||
attempts := 1000
|
||||
threads := 4
|
||||
|
||||
|
|
@ -64,6 +60,18 @@ func test18146(t *testing.T) {
|
|||
cmd.Stdout = buf
|
||||
cmd.Stderr = buf
|
||||
if err := cmd.Start(); err != nil {
|
||||
// We are starting so many processes that on
|
||||
// some systems (problem seen on Darwin,
|
||||
// Dragonfly, OpenBSD) the fork call will fail
|
||||
// with EAGAIN.
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
err = pe.Err
|
||||
}
|
||||
if se, ok := err.(syscall.Errno); ok && se == syscall.EAGAIN {
|
||||
time.Sleep(time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "libcgo.h"
|
||||
|
|
@ -48,3 +51,24 @@ void x_cgo_set_context_function(void (*context)(struct context_arg*)) {
|
|||
void (*(_cgo_get_context_function(void)))(struct context_arg*) {
|
||||
return cgo_context_function;
|
||||
}
|
||||
|
||||
// _cgo_try_pthread_create retries sys_pthread_create if it fails with
|
||||
// EAGAIN.
|
||||
int
|
||||
_cgo_openbsd_try_pthread_create(int (*sys_pthread_create)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*),
|
||||
pthread_t* thread, const pthread_attr_t* attr, void* (*pfn)(void*), void* arg) {
|
||||
int tries;
|
||||
int err;
|
||||
struct timespec ts;
|
||||
|
||||
for (tries = 0; tries < 100; tries++) {
|
||||
err = sys_pthread_create(thread, attr, pfn, arg);
|
||||
if (err != EAGAIN) {
|
||||
return err;
|
||||
}
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = (tries + 1) * 1000 * 1000; // Milliseconds.
|
||||
nanosleep(&ts, nil);
|
||||
}
|
||||
return EAGAIN;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include "libcgo.h"
|
||||
#include "libcgo_unix.h"
|
||||
|
||||
static void* threadentry(void*);
|
||||
static void (*setg_gcc)(void*);
|
||||
|
|
@ -170,7 +171,7 @@ _cgo_sys_thread_start(ThreadStart *ts)
|
|||
|
||||
// Leave stacklo=0 and set stackhi=size; mstack will do the rest.
|
||||
ts->g->stackhi = size;
|
||||
err = sys_pthread_create(&p, &attr, threadentry, ts);
|
||||
err = _cgo_openbsd_try_pthread_create(sys_pthread_create, &p, &attr, threadentry, ts);
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &oset, nil);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include "libcgo.h"
|
||||
#include "libcgo_unix.h"
|
||||
|
||||
static void* threadentry(void*);
|
||||
static void (*setg_gcc)(void*);
|
||||
|
|
@ -170,7 +171,7 @@ _cgo_sys_thread_start(ThreadStart *ts)
|
|||
|
||||
// Leave stacklo=0 and set stackhi=size; mstack will do the rest.
|
||||
ts->g->stackhi = size;
|
||||
err = sys_pthread_create(&p, &attr, threadentry, ts);
|
||||
err = _cgo_openbsd_try_pthread_create(sys_pthread_create, &p, &attr, threadentry, ts);
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &oset, nil);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,4 +5,11 @@
|
|||
/*
|
||||
* Call pthread_create, retrying on EAGAIN.
|
||||
*/
|
||||
int _cgo_try_pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*);
|
||||
extern int _cgo_try_pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*);
|
||||
|
||||
/*
|
||||
* Same as _cgo_try_pthread_create, but passing on the pthread_create function.
|
||||
* Only defined on OpenBSD.
|
||||
*/
|
||||
extern int _cgo_openbsd_try_pthread_create(int (*)(pthread_t*, const pthread_attr_t*, void *(*pfn)(void*), void*),
|
||||
pthread_t*, const pthread_attr_t*, void* (*)(void*), void* arg);
|
||||
|
|
|
|||
Loading…
Reference in New Issue