Skip to content

Commit 07f1bb0

Browse files
cjihrigaddaleax
authored andcommitted
process: allow reading umask in workers
Refs: #25448 PR-URL: #25526 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent ab86143 commit 07f1bb0

10 files changed

+54
-12
lines changed

doc/api/errors.md

+5
Original file line numberDiff line numberDiff line change
@@ -1880,6 +1880,11 @@ All attempts at serializing an uncaught exception from a worker thread failed.
18801880
The pathname used for the main script of a worker has an
18811881
unknown file extension.
18821882

1883+
<a id="ERR_WORKER_UNSUPPORTED_OPERATION"></a>
1884+
### ERR_WORKER_UNSUPPORTED_OPERATION
1885+
1886+
The requested functionality is not supported in worker threads.
1887+
18831888
<a id="ERR_ZLIB_INITIALIZATION_FAILED"></a>
18841889
### ERR_ZLIB_INITIALIZATION_FAILED
18851890

doc/api/process.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -2007,7 +2007,8 @@ console.log(
20072007
);
20082008
```
20092009

2010-
This feature is not available in [`Worker`][] threads.
2010+
[`Worker`][] threads are able to read the umask, however attempting to set the
2011+
umask will result in a thrown exception.
20112012

20122013
## process.uptime()
20132014
<!-- YAML

lib/internal/bootstrap/node.js

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ function startup() {
8282
process._startProfilerIdleNotifier =
8383
rawMethods._startProfilerIdleNotifier;
8484
process._stopProfilerIdleNotifier = rawMethods._stopProfilerIdleNotifier;
85+
} else {
86+
const wrapped = workerThreadSetup.wrapProcessMethods(rawMethods);
87+
88+
process.umask = wrapped.umask;
8589
}
8690

8791
// Set up methods on the process object for all threads

lib/internal/errors.js

+2
Original file line numberDiff line numberDiff line change
@@ -976,4 +976,6 @@ E('ERR_WORKER_UNSERIALIZABLE_ERROR',
976976
E('ERR_WORKER_UNSUPPORTED_EXTENSION',
977977
'The worker script extension must be ".js" or ".mjs". Received "%s"',
978978
TypeError);
979+
E('ERR_WORKER_UNSUPPORTED_OPERATION',
980+
'%s is not supported in workers', TypeError);
979981
E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error);

lib/internal/process/worker_thread_only.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ const {
1515
WritableWorkerStdio
1616
} = require('internal/worker/io');
1717

18+
const {
19+
codes: { ERR_WORKER_UNSUPPORTED_OPERATION }
20+
} = require('internal/errors');
21+
1822
let debuglog;
1923
function debug(...args) {
2024
if (!debuglog) {
@@ -118,8 +122,23 @@ function createWorkerFatalExeception(port) {
118122
};
119123
}
120124

125+
// The execution of this function itself should not cause any side effects.
126+
function wrapProcessMethods(binding) {
127+
function umask(mask) {
128+
// process.umask() is a read-only operation in workers.
129+
if (mask !== undefined) {
130+
throw new ERR_WORKER_UNSUPPORTED_OPERATION('Setting process.umask()');
131+
}
132+
133+
return binding.umask(mask);
134+
}
135+
136+
return { umask };
137+
}
138+
121139
module.exports = {
122140
initializeWorkerStdio,
123141
createMessageHandler,
124-
createWorkerFatalExeception
142+
createWorkerFatalExeception,
143+
wrapProcessMethods
125144
};

src/node_process_methods.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ using v8::Uint32;
5050
using v8::Uint32Array;
5151
using v8::Value;
5252

53+
namespace per_process {
54+
Mutex umask_mutex;
55+
} // namespace per_process
56+
5357
// Microseconds in a second, as a float, used in CPUUsage() below
5458
#define MICROS_PER_SEC 1e6
5559
// used in Hrtime() below
@@ -220,6 +224,7 @@ static void Umask(const FunctionCallbackInfo<Value>& args) {
220224

221225
CHECK_EQ(args.Length(), 1);
222226
CHECK(args[0]->IsUndefined() || args[0]->IsUint32());
227+
Mutex::ScopedLock scoped_lock(per_process::umask_mutex);
223228

224229
if (args[0]->IsUndefined()) {
225230
old = umask(0);
@@ -396,9 +401,9 @@ static void InitializeProcessMethods(Local<Object> target,
396401
target, "_stopProfilerIdleNotifier", StopProfilerIdleNotifier);
397402
env->SetMethod(target, "abort", Abort);
398403
env->SetMethod(target, "chdir", Chdir);
399-
env->SetMethod(target, "umask", Umask);
400404
}
401405

406+
env->SetMethod(target, "umask", Umask);
402407
env->SetMethod(target, "_rawDebug", RawDebug);
403408
env->SetMethod(target, "memoryUsage", MemoryUsage);
404409
env->SetMethod(target, "cpuUsage", CPUUsage);

test/common/index.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,20 @@ const {
3333
bits,
3434
hasIntl
3535
} = process.binding('config');
36+
const { isMainThread } = require('worker_threads');
3637

3738
// Some tests assume a umask of 0o022 so set that up front. Tests that need a
3839
// different umask will set it themselves.
3940
//
40-
// process.umask() is not available in workers so we need to check for its
41-
// existence.
42-
if (process.umask)
41+
// Workers can read, but not set the umask, so check that this is the main
42+
// thread.
43+
if (isMainThread)
4344
process.umask(0o022);
4445

4546
const noop = () => {};
4647

4748
const hasCrypto = Boolean(process.versions.openssl);
4849

49-
const { isMainThread } = require('worker_threads');
50-
5150
// Check for flags. Skip this for workers (both, the `cluster` module and
5251
// `worker_threads`) and child processes.
5352
if (process.argv.length === 2 &&

test/parallel/test-fs-write-file-sync.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
const common = require('../common');
2424

2525
if (!common.isMainThread)
26-
common.skip('process.umask is not available in Workers');
26+
common.skip('Setting process.umask is not supported in Workers');
2727

2828
const assert = require('assert');
2929
const path = require('path');

test/parallel/test-process-umask-mask.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const common = require('../common');
77
const assert = require('assert');
88

99
if (!common.isMainThread)
10-
common.skip('process.umask is not available in Workers');
10+
common.skip('Setting process.umask is not supported in Workers');
1111

1212
let mask;
1313

test/parallel/test-process-umask.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,15 @@
2222
'use strict';
2323
const common = require('../common');
2424
const assert = require('assert');
25-
if (!common.isMainThread)
26-
common.skip('process.umask is not available in Workers');
25+
26+
if (!common.isMainThread) {
27+
assert.strictEqual(typeof process.umask(), 'number');
28+
assert.throws(() => {
29+
process.umask('0664');
30+
}, { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' });
31+
32+
common.skip('Setting process.umask is not supported in Workers');
33+
}
2734

2835
// Note in Windows one can only set the "user" bits.
2936
let mask;

0 commit comments

Comments
 (0)