zlib: switch to lazy init for zlib streams · nodejs/node@d60b13f · GitHub
Skip to content

Commit d60b13f

Browse files
puzpuzpuzaddaleax
authored andcommitted
zlib: switch to lazy init for zlib streams
PR-URL: #34048 Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 8cb306e commit d60b13f

3 files changed

Lines changed: 92 additions & 26 deletions

File tree

lib/zlib.js

Lines changed: 10 additions & 12 deletions

src/node_zlib.cc

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ class ZlibContext : public MemoryRetainer {
139139
CompressionError ResetStream();
140140

141141
// Zlib-specific:
142-
CompressionError Init(int level, int window_bits, int mem_level, int strategy,
143-
std::vector<unsigned char>&& dictionary);
142+
void Init(int level, int window_bits, int mem_level, int strategy,
143+
std::vector<unsigned char>&& dictionary);
144144
void SetAllocationFunctions(alloc_func alloc, free_func free, void* opaque);
145145
CompressionError SetParams(int level, int strategy);
146146

@@ -157,7 +157,10 @@ class ZlibContext : public MemoryRetainer {
157157
private:
158158
CompressionError ErrorForMessage(const char* message) const;
159159
CompressionError SetDictionary();
160+
bool InitZlib();
160161

162+
Mutex mutex_; // Protects zlib_init_done_.
163+
bool zlib_init_done_ = false;
161164
int err_ = 0;
162165
int flush_ = 0;
163166
int level_ = 0;
@@ -614,13 +617,8 @@ class ZlibStream : public CompressionStream<ZlibContext> {
614617
AllocScope alloc_scope(wrap);
615618
wrap->context()->SetAllocationFunctions(
616619
AllocForZlib, FreeForZlib, static_cast<CompressionStream*>(wrap));
617-
const CompressionError err =
618-
wrap->context()->Init(level, window_bits, mem_level, strategy,
619-
std::move(dictionary));
620-
if (err.IsError())
621-
wrap->EmitError(err);
622-
623-
return args.GetReturnValue().Set(!err.IsError());
620+
wrap->context()->Init(level, window_bits, mem_level, strategy,
621+
std::move(dictionary));
624622
}
625623

626624
static void Params(const FunctionCallbackInfo<Value>& args) {
@@ -723,6 +721,15 @@ using BrotliEncoderStream = BrotliCompressionStream<BrotliEncoderContext>;
723721
using BrotliDecoderStream = BrotliCompressionStream<BrotliDecoderContext>;
724722

725723
void ZlibContext::Close() {
724+
{
725+
Mutex::ScopedLock lock(mutex_);
726+
if (!zlib_init_done_) {
727+
dictionary_.clear();
728+
mode_ = NONE;
729+
return;
730+
}
731+
}
732+
726733
CHECK_LE(mode_, UNZIP);
727734

728735
int status = Z_OK;
@@ -741,6 +748,11 @@ void ZlibContext::Close() {
741748

742749

743750
void ZlibContext::DoThreadPoolWork() {
751+
bool first_init_call = InitZlib();
752+
if (first_init_call && err_ != Z_OK) {
753+
return;
754+
}
755+
744756
const Bytef* next_expected_header_byte = nullptr;
745757

746758
// If the avail_out is left at 0, then it means that it ran out
@@ -896,6 +908,11 @@ CompressionError ZlibContext::GetErrorInfo() const {
896908

897909

898910
CompressionError ZlibContext::ResetStream() {
911+
bool first_init_call = InitZlib();
912+
if (first_init_call && err_ != Z_OK) {
913+
return ErrorForMessage("Failed to init stream before reset");
914+
}
915+
899916
err_ = Z_OK;
900917

901918
switch (mode_) {
@@ -929,7 +946,7 @@ void ZlibContext::SetAllocationFunctions(alloc_func alloc,
929946
}
930947

931948

932-
CompressionError ZlibContext::Init(
949+
void ZlibContext::Init(
933950
int level, int window_bits, int mem_level, int strategy,
934951
std::vector<unsigned char>&& dictionary) {
935952
if (!((window_bits == 0) &&
@@ -973,6 +990,15 @@ CompressionError ZlibContext::Init(
973990
window_bits_ *= -1;
974991
}
975992

993+
dictionary_ = std::move(dictionary);
994+
}
995+
996+
bool ZlibContext::InitZlib() {
997+
Mutex::ScopedLock lock(mutex_);
998+
if (zlib_init_done_) {
999+
return false;
1000+
}
1001+
9761002
switch (mode_) {
9771003
case DEFLATE:
9781004
case GZIP:
@@ -994,15 +1020,15 @@ CompressionError ZlibContext::Init(
9941020
UNREACHABLE();
9951021
}
9961022

997-
dictionary_ = std::move(dictionary);
998-
9991023
if (err_ != Z_OK) {
10001024
dictionary_.clear();
10011025
mode_ = NONE;
1002-
return ErrorForMessage("zlib error");
1026+
return true;
10031027
}
10041028

1005-
return SetDictionary();
1029+
SetDictionary();
1030+
zlib_init_done_ = true;
1031+
return true;
10061032
}
10071033

10081034

@@ -1039,6 +1065,11 @@ CompressionError ZlibContext::SetDictionary() {
10391065

10401066

10411067
CompressionError ZlibContext::SetParams(int level, int strategy) {
1068+
bool first_init_call = InitZlib();
1069+
if (first_init_call && err_ != Z_OK) {
1070+
return ErrorForMessage("Failed to init stream before set parameters");
1071+
}
1072+
10421073
err_ = Z_OK;
10431074

10441075
switch (mode_) {
Lines changed: 37 additions & 0 deletions

0 commit comments

Comments
 (0)