Skip to content

Commit 6585859

Browse files
authored
crypto: load system CA certificates off thread
When --use-system-ca is enabled, load the system CA certificates eagerly off the main thread to avoid blocking the main thread when the first TLS connection is made. PR-URL: nodejs#59550 Refs: nodejs#58990 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 323f19c commit 6585859

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

src/crypto/crypto_context.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,23 @@ static std::vector<X509*>& GetSystemStoreCACertificates() {
814814
return system_store_certs;
815815
}
816816

817+
static void LoadSystemCACertificates(void* data) {
818+
GetSystemStoreCACertificates();
819+
}
820+
821+
static uv_thread_t system_ca_thread;
822+
static bool system_ca_thread_started = false;
823+
int LoadSystemCACertificatesOffThread() {
824+
// This is only run once during the initialization of the process, so
825+
// it is safe to use a static thread here.
826+
int r =
827+
uv_thread_create(&system_ca_thread, LoadSystemCACertificates, nullptr);
828+
if (r == 0) {
829+
system_ca_thread_started = true;
830+
}
831+
return r;
832+
}
833+
817834
static std::vector<X509*> InitializeExtraCACertificates() {
818835
std::vector<X509*> extra_certs;
819836
unsigned long err = LoadCertsFromFile( // NOLINT(runtime/int)
@@ -925,6 +942,10 @@ void CleanupCachedRootCertificates() {
925942
X509_free(cert);
926943
}
927944
}
945+
if (system_ca_thread_started) {
946+
uv_thread_join(&system_ca_thread);
947+
system_ca_thread_started = false;
948+
}
928949
}
929950

930951
void GetBundledRootCertificates(const FunctionCallbackInfo<Value>& args) {

src/crypto/crypto_util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void InitCryptoOnce();
4545
void InitCrypto(v8::Local<v8::Object> target);
4646

4747
extern void UseExtraCaCerts(std::string_view file);
48+
extern int LoadSystemCACertificatesOffThread();
4849
void CleanupCachedRootCertificates();
4950

5051
int PasswordCallback(char* buf, int size, int rwflag, void* u);

src/node.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,20 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
12001200
return result;
12011201
}
12021202

1203+
if (per_process::cli_options->use_system_ca) {
1204+
// Load the system CA certificates eagerly off the main thread to avoid
1205+
// blocking the main thread when the first TLS connection is made. We
1206+
// don't need to wait for the thread to finish with code here, as
1207+
// GetSystemStoreCACertificates() has a function-local static and any
1208+
// actual user of it will wait for that to complete initialization.
1209+
int r = crypto::LoadSystemCACertificatesOffThread();
1210+
if (r != 0) {
1211+
FPrintF(
1212+
stderr,
1213+
"Warning: Failed to load system CA certificates off thread: %s\n",
1214+
uv_strerror(r));
1215+
}
1216+
}
12031217
// Ensure CSPRNG is properly seeded.
12041218
CHECK(ncrypto::CSPRNG(nullptr, 0));
12051219

0 commit comments

Comments
 (0)