Skip to content

Commit 40ee688

Browse files
committed
process: respect Float64Array byte offsets
Account for Float64Array byte offsets when writing CPU, thread CPU, memory, and resource usage values. Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com>
1 parent 985aa07 commit 40ee688

2 files changed

Lines changed: 45 additions & 14 deletions

File tree

‎src/node_process_methods.cc‎

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ typedef int mode_t;
4040
namespace node {
4141

4242
using v8::Array;
43-
using v8::ArrayBuffer;
4443
using v8::CFunction;
4544
using v8::Context;
4645
using v8::Float64Array;
@@ -100,14 +99,14 @@ static void Chdir(const FunctionCallbackInfo<Value>& args) {
10099
}
101100
}
102101

103-
inline Local<ArrayBuffer> get_fields_array_buffer(
104-
const FunctionCallbackInfo<Value>& args,
105-
size_t index,
106-
size_t array_length) {
102+
inline double* get_fields_array_data(const FunctionCallbackInfo<Value>& args,
103+
size_t index,
104+
size_t array_length) {
107105
CHECK(args[index]->IsFloat64Array());
108106
Local<Float64Array> arr = args[index].As<Float64Array>();
109107
CHECK_EQ(arr->Length(), array_length);
110-
return arr->Buffer();
108+
uint8_t* data = static_cast<uint8_t*>(arr->Buffer()->Data());
109+
return reinterpret_cast<double*>(data + arr->ByteOffset());
111110
}
112111

113112
// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
@@ -125,8 +124,7 @@ static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
125124
return env->ThrowUVException(err, "uv_getrusage");
126125

127126
// Get the double array pointer from the Float64Array argument.
128-
Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 2);
129-
double* fields = static_cast<double*>(ab->Data());
127+
double* fields = get_fields_array_data(args, 0, 2);
130128

131129
// Set the Float64Array elements to be user / system values in microseconds.
132130
fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
@@ -148,8 +146,7 @@ static void ThreadCPUUsage(const FunctionCallbackInfo<Value>& args) {
148146
if (err) return env->ThrowUVException(err, "uv_getrusage_thread");
149147

150148
// Get the double array pointer from the Float64Array argument.
151-
Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 2);
152-
double* fields = static_cast<double*>(ab->Data());
149+
double* fields = get_fields_array_data(args, 0, 2);
153150

154151
// Set the Float64Array elements to be user / system values in microseconds.
155152
fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
@@ -230,8 +227,7 @@ static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
230227
env->isolate_data()->node_allocator();
231228

232229
// Get the double array pointer from the Float64Array argument.
233-
Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 5);
234-
double* fields = static_cast<double*>(ab->Data());
230+
double* fields = get_fields_array_data(args, 0, 5);
235231

236232
size_t rss;
237233
int err = uv_resident_set_memory(&rss);
@@ -369,8 +365,7 @@ static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
369365
if (err)
370366
return env->ThrowUVException(err, "uv_getrusage");
371367

372-
Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 16);
373-
double* fields = static_cast<double*>(ab->Data());
368+
double* fields = get_fields_array_data(args, 0, 16);
374369

375370
fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
376371
fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
const common = require('../common');
5+
const assert = require('assert');
6+
const { internalBinding } = require('internal/test/binding');
7+
8+
const binding = internalBinding('process_methods');
9+
const methods = [
10+
['cpuUsage', 2],
11+
['memoryUsage', 5],
12+
['resourceUsage', 16],
13+
];
14+
15+
if (!common.isSunOS) {
16+
methods.push(['threadCpuUsage', 2]);
17+
}
18+
19+
for (const [method, length] of methods) {
20+
const values = new Float64Array(length + 1);
21+
values.fill(-1);
22+
values[0] = 42;
23+
24+
const fields = new Float64Array(
25+
values.buffer,
26+
Float64Array.BYTES_PER_ELEMENT,
27+
length,
28+
);
29+
30+
binding[method](fields);
31+
32+
assert.strictEqual(values[0], 42, `${method} wrote before the target view`);
33+
for (const value of fields) {
34+
assert(value >= 0, `${method} did not populate the target view`);
35+
}
36+
}

0 commit comments

Comments
 (0)