Skip to content

Commit 80acfe9

Browse files
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent a303f05 commit 80acfe9

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

misc/cgo/test/issue18146.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,10 @@ import (
1818
"runtime"
1919
"syscall"
2020
"testing"
21+
"time"
2122
)
2223

2324
func test18146(t *testing.T) {
24-
switch runtime.GOOS {
25-
case "darwin", "openbsd", "dragonfly":
26-
t.Skip("skipping on %s; issue 18146", runtime.GOOS)
27-
}
28-
2925
attempts := 1000
3026
threads := 4
3127

@@ -64,6 +60,18 @@ func test18146(t *testing.T) {
6460
cmd.Stdout = buf
6561
cmd.Stderr = buf
6662
if err := cmd.Start(); err != nil {
63+
// We are starting so many processes that on
64+
// some systems (problem seen on Darwin,
65+
// Dragonfly, OpenBSD) the fork call will fail
66+
// with EAGAIN.
67+
if pe, ok := err.(*os.PathError); ok {
68+
err = pe.Err
69+
}
70+
if se, ok := err.(syscall.Errno); ok && se == syscall.EAGAIN {
71+
time.Sleep(time.Millisecond)
72+
continue
73+
}
74+
6775
t.Error(err)
6876
return
6977
}

src/runtime/cgo/gcc_libinit_openbsd.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
#include <sys/types.h>
6+
#include <errno.h>
7+
#include <pthread.h>
58
#include <stdio.h>
69
#include <stdlib.h>
710
#include "libcgo.h"
@@ -48,3 +51,24 @@ void x_cgo_set_context_function(void (*context)(struct context_arg*)) {
4851
void (*(_cgo_get_context_function(void)))(struct context_arg*) {
4952
return cgo_context_function;
5053
}
54+
55+
// _cgo_try_pthread_create retries sys_pthread_create if it fails with
56+
// EAGAIN.
57+
int
58+
_cgo_openbsd_try_pthread_create(int (*sys_pthread_create)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*),
59+
pthread_t* thread, const pthread_attr_t* attr, void* (*pfn)(void*), void* arg) {
60+
int tries;
61+
int err;
62+
struct timespec ts;
63+
64+
for (tries = 0; tries < 100; tries++) {
65+
err = sys_pthread_create(thread, attr, pfn, arg);
66+
if (err != EAGAIN) {
67+
return err;
68+
}
69+
ts.tv_sec = 0;
70+
ts.tv_nsec = (tries + 1) * 1000 * 1000; // Milliseconds.
71+
nanosleep(&ts, nil);
72+
}
73+
return EAGAIN;
74+
}

src/runtime/cgo/gcc_openbsd_386.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <signal.h>
1010
#include <string.h>
1111
#include "libcgo.h"
12+
#include "libcgo_unix.h"
1213

1314
static void* threadentry(void*);
1415
static void (*setg_gcc)(void*);
@@ -170,7 +171,7 @@ _cgo_sys_thread_start(ThreadStart *ts)
170171

171172
// Leave stacklo=0 and set stackhi=size; mstack will do the rest.
172173
ts->g->stackhi = size;
173-
err = sys_pthread_create(&p, &attr, threadentry, ts);
174+
err = _cgo_openbsd_try_pthread_create(sys_pthread_create, &p, &attr, threadentry, ts);
174175

175176
pthread_sigmask(SIG_SETMASK, &oset, nil);
176177

src/runtime/cgo/gcc_openbsd_amd64.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <signal.h>
1010
#include <string.h>
1111
#include "libcgo.h"
12+
#include "libcgo_unix.h"
1213

1314
static void* threadentry(void*);
1415
static void (*setg_gcc)(void*);
@@ -170,7 +171,7 @@ _cgo_sys_thread_start(ThreadStart *ts)
170171

171172
// Leave stacklo=0 and set stackhi=size; mstack will do the rest.
172173
ts->g->stackhi = size;
173-
err = sys_pthread_create(&p, &attr, threadentry, ts);
174+
err = _cgo_openbsd_try_pthread_create(sys_pthread_create, &p, &attr, threadentry, ts);
174175

175176
pthread_sigmask(SIG_SETMASK, &oset, nil);
176177

src/runtime/cgo/libcgo_unix.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,11 @@
55
/*
66
* Call pthread_create, retrying on EAGAIN.
77
*/
8-
int _cgo_try_pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*);
8+
extern int _cgo_try_pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*);
9+
10+
/*
11+
* Same as _cgo_try_pthread_create, but passing on the pthread_create function.
12+
* Only defined on OpenBSD.
13+
*/
14+
extern int _cgo_openbsd_try_pthread_create(int (*)(pthread_t*, const pthread_attr_t*, void *(*pfn)(void*), void*),
15+
pthread_t*, const pthread_attr_t*, void* (*)(void*), void* arg);

0 commit comments

Comments
 (0)