Skip to content

Commit 8ee559b

Browse files
RafaelGSStheanarkh
authored andcommitted
lib: reuse invalid state errors on webstreams
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com> PR-URL: nodejs#46086 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 5d50b84 commit 8ee559b

File tree

6 files changed

+70
-0
lines changed

6 files changed

+70
-0
lines changed

doc/api/process.md

+15
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,21 @@ and [Cluster][] documentation), the `process.connected` property will return
11031103
Once `process.connected` is `false`, it is no longer possible to send messages
11041104
over the IPC channel using `process.send()`.
11051105

1106+
## `process.constrainedMemory()`
1107+
1108+
<!-- YAML
1109+
added: REPLACEME
1110+
-->
1111+
1112+
* {number}
1113+
1114+
Gets the amount of memory available to the process (in bytes) based on
1115+
limits imposed by the OS. If there is no such constraint, or the constraint
1116+
is unknown, `0` is returned. It is not unusual for this value to
1117+
be less than or greater than `os.totalmem()`. This function currently only
1118+
returns a non-zero value on Linux, based on cgroups if it is present, and
1119+
on z/OS based on `RLIMIT_MEMLIMIT`.
1120+
11061121
## `process.cpuUsage([previousValue])`
11071122

11081123
<!-- YAML

lib/internal/bootstrap/node.js

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ const rawMethods = internalBinding('process_methods');
184184

185185
process.hrtime = perThreadSetup.hrtime;
186186
process.hrtime.bigint = perThreadSetup.hrtimeBigInt;
187+
process.constrainedMemory = perThreadSetup.constrainedMemory;
187188

188189
process.openStdin = function() {
189190
process.stdin.resume();

lib/internal/process/per_thread.js

+8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const binding = internalBinding('process_methods');
6060

6161
let hrValues;
6262
let hrBigintValues;
63+
let constrainedMemoryValus;
6364

6465
function refreshHrtimeBuffer() {
6566
// The 3 entries filled in by the original process.hrtime contains
@@ -69,6 +70,7 @@ function refreshHrtimeBuffer() {
6970
// Use a BigUint64Array in the closure because this is actually a bit
7071
// faster than simply returning a BigInt from C++ in V8 7.1.
7172
hrBigintValues = new BigUint64Array(binding.hrtimeBuffer, 0, 1);
73+
constrainedMemoryValus = new BigUint64Array(binding.hrtimeBuffer, 0, 1);
7274
}
7375

7476
// Create the buffers.
@@ -100,6 +102,11 @@ function hrtimeBigInt() {
100102
return hrBigintValues[0];
101103
}
102104

105+
function constrainedMemory() {
106+
binding.constrainedMemory();
107+
return constrainedMemoryValus[0];
108+
}
109+
103110
function nop() {}
104111

105112
// The execution of this function itself should not cause any side effects.
@@ -427,4 +434,5 @@ module.exports = {
427434
hrtime,
428435
hrtimeBigInt,
429436
refreshHrtimeBuffer,
437+
constrainedMemory,
430438
};

src/node_process.h

+6
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ class BindingData : public SnapshotableObject {
8181

8282
static void SlowBigInt(const v8::FunctionCallbackInfo<v8::Value>& args);
8383

84+
static void ConstrainedMemoryImpl(BindingData* receiver);
85+
static void SlowGetConstrainedMemory(
86+
const v8::FunctionCallbackInfo<v8::Value>& args);
87+
static void FastGetConstrainedMemory(v8::Local<v8::Value> receiver);
88+
8489
private:
8590
static constexpr size_t kBufferSize =
8691
std::max(sizeof(uint64_t), sizeof(uint32_t) * 3);
@@ -92,6 +97,7 @@ class BindingData : public SnapshotableObject {
9297
// time.
9398
static v8::CFunction fast_number_;
9499
static v8::CFunction fast_bigint_;
100+
static v8::CFunction fast_get_constrained_memory_;
95101
};
96102

97103
} // namespace process

src/node_process_methods.cc

+27
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,18 @@ BindingData::BindingData(Environment* env, v8::Local<v8::Object> object)
471471

472472
v8::CFunction BindingData::fast_number_(v8::CFunction::Make(FastNumber));
473473
v8::CFunction BindingData::fast_bigint_(v8::CFunction::Make(FastBigInt));
474+
v8::CFunction BindingData::fast_get_constrained_memory_ =
475+
v8::CFunction::Make(FastGetConstrainedMemory);
474476

475477
void BindingData::AddMethods() {
476478
Local<Context> ctx = env()->context();
477479
SetFastMethod(ctx, object(), "hrtime", SlowNumber, &fast_number_);
478480
SetFastMethod(ctx, object(), "hrtimeBigInt", SlowBigInt, &fast_bigint_);
481+
SetFastMethod(ctx,
482+
object(),
483+
"constrainedMemory",
484+
SlowGetConstrainedMemory,
485+
&fast_get_constrained_memory_);
479486
}
480487

481488
void BindingData::RegisterExternalReferences(
@@ -486,6 +493,9 @@ void BindingData::RegisterExternalReferences(
486493
registry->Register(FastBigInt);
487494
registry->Register(fast_number_.GetTypeInfo());
488495
registry->Register(fast_bigint_.GetTypeInfo());
496+
registry->Register(SlowGetConstrainedMemory);
497+
registry->Register(FastGetConstrainedMemory);
498+
registry->Register(fast_get_constrained_memory_.GetTypeInfo());
489499
}
490500

491501
BindingData* BindingData::FromV8Value(Local<Value> value) {
@@ -533,6 +543,23 @@ void BindingData::SlowNumber(const v8::FunctionCallbackInfo<v8::Value>& args) {
533543
NumberImpl(FromJSObject<BindingData>(args.Holder()));
534544
}
535545

546+
void BindingData::ConstrainedMemoryImpl(BindingData* receiver) {
547+
// Make sure we don't accidentally access buffers wiped for snapshot.
548+
CHECK(!receiver->array_buffer_.IsEmpty());
549+
uint64_t t = uv_get_constrained_memory();
550+
uint64_t* fields = static_cast<uint64_t*>(receiver->backing_store_->Data());
551+
fields[0] = t;
552+
}
553+
554+
void BindingData::SlowGetConstrainedMemory(
555+
const FunctionCallbackInfo<Value>& args) {
556+
ConstrainedMemoryImpl(FromJSObject<BindingData>(args.Holder()));
557+
}
558+
559+
void BindingData::FastGetConstrainedMemory(v8::Local<v8::Value> receiver) {
560+
ConstrainedMemoryImpl(FromV8Value(receiver));
561+
}
562+
536563
bool BindingData::PrepareForSerialization(Local<Context> context,
537564
v8::SnapshotCreator* creator) {
538565
// It's not worth keeping.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const { Worker } = require('worker_threads');
5+
6+
7+
if (!process.env.isWorker) {
8+
process.env.isWorker = true;
9+
new Worker(__filename);
10+
assert(process.constrainedMemory() >= 0);
11+
} else {
12+
assert(process.constrainedMemory() >= 0);
13+
}

0 commit comments

Comments
 (0)