"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
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
}
// 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"
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;
+}
#include <signal.h>
#include <string.h>
#include "libcgo.h"
+#include "libcgo_unix.h"
static void* threadentry(void*);
static void (*setg_gcc)(void*);
// 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);
#include <signal.h>
#include <string.h>
#include "libcgo.h"
+#include "libcgo_unix.h"
static void* threadentry(void*);
static void (*setg_gcc)(void*);
// 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);
/*
* 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);