8268773: Improvements related to: Failed to start thread - pthread_create failed (EAGAIN)

Reviewed-by: stuefe, iklam
This commit is contained in:
David Holmes 2021-07-16 02:49:40 +00:00
parent ea77ef8348
commit e35005d5ce
8 changed files with 75 additions and 29 deletions

View file

@ -814,19 +814,24 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
ret = pthread_attr_setguardsize(&attr, 0); ret = pthread_attr_setguardsize(&attr, 0);
} }
ResourceMark rm;
pthread_t tid = 0; pthread_t tid = 0;
if (ret == 0) { if (ret == 0) {
int limit = 3;
do {
ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread); ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
} while (ret == EAGAIN && limit-- > 0);
} }
if (ret == 0) { if (ret == 0) {
char buf[64]; char buf[64];
log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", log_info(os, thread)("Thread \"%s\" started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
(uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); thread->name(), (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
} else { } else {
char buf[64]; char buf[64];
log_warning(os, thread)("Failed to start thread - pthread_create failed (%d=%s) for attributes: %s.", log_warning(os, thread)("Failed to start thread \"%s\" - pthread_create failed (%d=%s) for attributes: %s.",
ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); thread->name(), ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
// Log some OS information which might explain why creating the thread failed. // Log some OS information which might explain why creating the thread failed.
log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads()); log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
LogStream st(Log(os, thread)::info()); LogStream st(Log(os, thread)::info());

View file

@ -631,16 +631,22 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
ThreadState state; ThreadState state;
{ {
ResourceMark rm;
pthread_t tid; pthread_t tid;
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread); int ret = 0;
int limit = 3;
do {
ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
} while (ret == EAGAIN && limit-- > 0);
char buf[64]; char buf[64];
if (ret == 0) { if (ret == 0) {
log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", log_info(os, thread)("Thread \"%s\" started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
(uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); thread->name(), (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
} else { } else {
log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", log_warning(os, thread)("Failed to start thread \"%s\" - pthread_create failed (%s) for attributes: %s.",
os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); thread->name(), os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
// Log some OS information which might explain why creating the thread failed. // Log some OS information which might explain why creating the thread failed.
log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads()); log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
LogStream st(Log(os, thread)::info()); LogStream st(Log(os, thread)::info());

View file

@ -863,16 +863,21 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
ThreadState state; ThreadState state;
{ {
ResourceMark rm;
pthread_t tid; pthread_t tid;
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread); int ret = 0;
int limit = 3;
do {
ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
} while (ret == EAGAIN && limit-- > 0);
char buf[64]; char buf[64];
if (ret == 0) { if (ret == 0) {
log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", log_info(os, thread)("Thread \"%s\" started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
(uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); thread->name(), (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
} else { } else {
log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", log_warning(os, thread)("Failed to start thread \"%s\" - pthread_create failed (%s) for attributes: %s.",
os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); thread->name(), os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
// Log some OS information which might explain why creating the thread failed. // Log some OS information which might explain why creating the thread failed.
log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads()); log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
LogStream st(Log(os, thread)::info()); LogStream st(Log(os, thread)::info());

View file

@ -743,21 +743,27 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
// flag appears to work with _beginthredex() as well. // flag appears to work with _beginthredex() as well.
const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION; const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION;
HANDLE thread_handle = HANDLE thread_handle;
int limit = 3;
do {
thread_handle =
(HANDLE)_beginthreadex(NULL, (HANDLE)_beginthreadex(NULL,
(unsigned)stack_size, (unsigned)stack_size,
(unsigned (__stdcall *)(void*)) thread_native_entry, (unsigned (__stdcall *)(void*)) thread_native_entry,
thread, thread,
initflag, initflag,
&thread_id); &thread_id);
} while (thread_handle == NULL && errno == EAGAIN && limit-- > 0);
ResourceMark rm;
char buf[64]; char buf[64];
if (thread_handle != NULL) { if (thread_handle != NULL) {
log_info(os, thread)("Thread started (tid: %u, attributes: %s)", log_info(os, thread)("Thread \"%s\" started (tid: %u, attributes: %s)",
thread_id, describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); thread->name(), thread_id,
describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));
} else { } else {
log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.", log_warning(os, thread)("Failed to start thread \"%s\" - _beginthreadex failed (%s) for attributes: %s.",
os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); thread->name(), os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));
// Log some OS information which might explain why creating the thread failed. // Log some OS information which might explain why creating the thread failed.
log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads()); log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
LogStream st(Log(os, thread)::info()); LogStream st(Log(os, thread)::info());

View file

@ -2909,6 +2909,9 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
assert(native_thread != NULL, "Starting null thread?"); assert(native_thread != NULL, "Starting null thread?");
if (native_thread->osthread() == NULL) { if (native_thread->osthread() == NULL) {
ResourceMark rm(thread);
log_warning(os, thread)("Failed to start the native thread for java.lang.Thread \"%s\"",
JavaThread::name_for(JNIHandles::resolve_non_null(jthread)));
// No one should hold a reference to the 'native_thread'. // No one should hold a reference to the 'native_thread'.
native_thread->smr_delete(); native_thread->smr_delete();
if (JvmtiExport::should_post_resource_exhausted()) { if (JvmtiExport::should_post_resource_exhausted()) {

View file

@ -446,6 +446,13 @@ bool Thread::is_JavaThread_protected(const JavaThread* p) {
return true; return true;
} }
// If the target hasn't been started yet then it is trivially
// "protected". We assume the caller is the thread that will do
// the starting.
if (p->osthread() == NULL || p->osthread()->get_state() <= INITIALIZED) {
return true;
}
// Now make the simple checks based on who the caller is: // Now make the simple checks based on who the caller is:
Thread* current_thread = Thread::current(); Thread* current_thread = Thread::current();
if (current_thread == p || Threads_lock->owner() == current_thread) { if (current_thread == p || Threads_lock->owner() == current_thread) {
@ -2146,7 +2153,7 @@ const char* JavaThread::name() const {
} }
// Returns a non-NULL representation of this thread's name, or a suitable // Returns a non-NULL representation of this thread's name, or a suitable
// descriptive string if there is no set name // descriptive string if there is no set name.
const char* JavaThread::get_thread_name_string(char* buf, int buflen) const { const char* JavaThread::get_thread_name_string(char* buf, int buflen) const {
const char* name_str; const char* name_str;
oop thread_obj = threadObj(); oop thread_obj = threadObj();
@ -2170,6 +2177,19 @@ const char* JavaThread::get_thread_name_string(char* buf, int buflen) const {
return name_str; return name_str;
} }
// Helper to extract the name from the thread oop for logging.
const char* JavaThread::name_for(oop thread_obj) {
assert(thread_obj != NULL, "precondition");
oop name = java_lang_Thread::name(thread_obj);
const char* name_str;
if (name != NULL) {
name_str = java_lang_String::as_utf8_string(name);
} else {
name_str = "<un-named>";
}
return name_str;
}
void JavaThread::prepare(jobject jni_thread, ThreadPriority prio) { void JavaThread::prepare(jobject jni_thread, ThreadPriority prio) {
assert(Threads_lock->owner() == Thread::current(), "must have threads lock"); assert(Threads_lock->owner() == Thread::current(), "must have threads lock");

View file

@ -1379,6 +1379,7 @@ class JavaThread: public Thread {
// Misc. operations // Misc. operations
const char* name() const; const char* name() const;
const char* type_name() const { return "JavaThread"; } const char* type_name() const { return "JavaThread"; }
static const char* name_for(oop thread_obj);
void print_on(outputStream* st, bool print_extended_info) const; void print_on(outputStream* st, bool print_extended_info) const;
void print_on(outputStream* st) const { print_on(st, false); } void print_on(outputStream* st) const { print_on(st, false); }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -41,7 +41,7 @@ import jdk.test.lib.process.ProcessTools;
public class ThreadLoggingTest { public class ThreadLoggingTest {
static void analyzeOutputForInfoLevel(OutputAnalyzer output) throws Exception { static void analyzeOutputForInfoLevel(OutputAnalyzer output) throws Exception {
output.shouldContain("Thread started"); output.shouldMatch("Thread .* started");
output.shouldContain("Thread is alive"); output.shouldContain("Thread is alive");
output.shouldContain("Thread finished"); output.shouldContain("Thread finished");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);