Skip to content

Commit 02dbcc4

Browse files
Nitzan Uzielydanielleadams
authored andcommitted
net: support abortSignal in server.listen
PR-URL: #36623 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 833e614 commit 02dbcc4

4 files changed

Lines changed: 70 additions & 1 deletion

File tree

‎doc/api/net.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ Listening on a file descriptor is not supported on Windows.
324324
<!-- YAML
325325
added: v0.11.14
326326
changes:
327+
- version: REPLACEME
328+
pr-url: https://github.com/nodejs/node/pull/36623
329+
description: AbortSignal support was added.
327330
- version: v11.4.0
328331
pr-url: https://github.com/nodejs/node/pull/23798
329332
description: The `ipv6Only` option is supported.
@@ -344,6 +347,7 @@ changes:
344347
*`ipv6Only` {boolean} For TCP servers, setting `ipv6Only` to `true` will
345348
disable dual-stack support, i.e., binding to host `::` won't make
346349
`0.0.0.0` be bound. **Default:**`false`.
350+
*`signal` {AbortSignal} An AbortSignal that may be used to close a listening server.
347351
*`callback` {Function}
348352
functions.
349353
* Returns: {net.Server}
@@ -375,6 +379,20 @@ Starting an IPC server as root may cause the server path to be inaccessible for
375379
unprivileged users. Using `readableAll` and `writableAll` will make the server
376380
accessible for all users.
377381

382+
If the `signal` option is enabled, calling `.abort()` on the corresponding
383+
`AbortController` is similar to calling `.close()` on the server:
384+
385+
```js
386+
constcontroller=newAbortController();
387+
server.listen({
388+
host:'localhost',
389+
port:80,
390+
signal:controller.signal
391+
});
392+
// Later, when you want to close the server.
393+
controller.abort();
394+
```
395+
378396
#### `server.listen(path[, backlog][, callback])`
379397
<!-- YAML
380398
added: v0.1.90

‎lib/internal/streams/add-abort-signal.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const eos = require('internal/streams/end-of-stream');
99
const{ERR_INVALID_ARG_TYPE}=codes;
1010

1111
// This method is inlined here for readable-stream
12-
// It also does not allow for signal to not exist on the steam
12+
// It also does not allow for signal to not exist on the stream
1313
// https://github.com/nodejs/node/pull/36061#discussion_r533718029
1414
constvalidateAbortSignal=(signal,name)=>{
1515
if(typeofsignal!=='object'||

‎lib/net.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ const {
109109
}=require('internal/errors');
110110
const{ isUint8Array }=require('internal/util/types');
111111
const{
112+
validateAbortSignal,
112113
validateInt32,
113114
validatePort,
114115
validateString
@@ -1148,6 +1149,22 @@ function afterConnect(status, handle, req, readable, writable) {
11481149
}
11491150
}
11501151

1152+
functionaddAbortSignalOption(self,options){
1153+
if(options?.signal===undefined){
1154+
return;
1155+
}
1156+
validateAbortSignal(options.signal,'options.signal');
1157+
const{ signal }=options;
1158+
constonAborted=()=>{
1159+
self.close();
1160+
};
1161+
if(signal.aborted){
1162+
process.nextTick(onAborted);
1163+
}else{
1164+
signal.addEventListener('abort',onAborted);
1165+
self.once('close',()=>signal.removeEventListener('abort',onAborted));
1166+
}
1167+
}
11511168

11521169
functionServer(options,connectionListener){
11531170
if(!(thisinstanceofServer))
@@ -1398,6 +1415,7 @@ Server.prototype.listen = function(...args) {
13981415
listenInCluster(this,null,-1,-1,backlogFromArgs);
13991416
returnthis;
14001417
}
1418+
addAbortSignalOption(this,options);
14011419
// (handle[, backlog][, cb]) where handle is an object with a fd
14021420
if(typeofoptions.fd==='number'&&options.fd>=0){
14031421
listenInCluster(this,null,null,null,backlogFromArgs,options.fd);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
constassert=require('assert');
4+
constnet=require('net');
5+
6+
{
7+
// Test bad signal.
8+
constserver=net.createServer();
9+
assert.throws(
10+
()=>server.listen({port: 0,signal: 'INVALID_SIGNAL'}),
11+
{
12+
code: 'ERR_INVALID_ARG_TYPE',
13+
name: 'TypeError'
14+
});
15+
}
16+
17+
{
18+
// Test close.
19+
constserver=net.createServer();
20+
constcontroller=newAbortController();
21+
server.on('close',common.mustCall());
22+
server.listen({port: 0,signal: controller.signal});
23+
controller.abort();
24+
}
25+
26+
{
27+
// Test close with pre-aborted signal.
28+
constserver=net.createServer();
29+
constcontroller=newAbortController();
30+
controller.abort();
31+
server.on('close',common.mustCall());
32+
server.listen({port: 0,signal: controller.signal});
33+
}

0 commit comments

Comments
 (0)