Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dgram: add maxSendQueueSize socket option #10902

Closed
wants to merge 1 commit into from
Closed

Conversation

cjihrig
Copy link
Contributor

@cjihrig cjihrig commented Jan 19, 2017

This commit adds a maxSendQueueSize option to dgram sockets. When used, this option prevents the socket's send queue from growing without an upper bound.

Note that the send queue contains bound send() functions. This option limits the number of outstanding sends, not the actual size of the data being sent.

This is a WIP because docs and tests are still needed. I wanted to get feedback first.

Fixes: nodejs/node-v0.x-archive#8705

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

dgram

@nodejs-github-bot nodejs-github-bot added the dgram Issues and PRs related to the dgram subsystem / UDP. label Jan 19, 2017
@cjihrig cjihrig added the semver-minor PRs that contain new features and should be released in the next minor version. label Jan 19, 2017
@sam-github
Copy link
Contributor

What problem is this solving that needs to be solved at this level? Would there be a followon PR for TCP and file? What is special about the accumulation of async actions for dgram as opposed to the others? Would exposing the bytes and asyncs queued as a number and letting user-land implement policies work?

@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 19, 2017

What problem is this solving that needs to be solved at this level?

nodejs/node-v0.x-archive#8705

Would there be a followon PR for TCP and file?

I don't think so. I don't think they need them.

What is special about the accumulation of async actions for dgram as opposed to the others?

As far as I can tell, if DNS is down, dgram send operations accumulate indefinitely. I haven't seen that behavior with net and files.

Would exposing the bytes and asyncs queued as a number and letting user-land implement policies work?

It would, but I would compare this to the highWaterMark of streams and maxBuffer of child process - settings that allow Node to perform checks for the user.

@lxe
Copy link

lxe commented Jan 20, 2017

cc @Raynos

@Raynos
Copy link
Contributor

Raynos commented Jan 20, 2017

@sam-github

net does not have this problem because there is a _buffer in ReadableStream that deals with this.

dgram has this problem because it's not a ReadableStream.

@Trott Trott added the wip Issues and PRs that are still a work in progress. label Jan 20, 2017
This commit adds the maxSendQueueSize option to dgram sockets.
When used, this option prevents the socket's send queue from
growing without an upper bound.
@cjihrig cjihrig changed the title WIP: dgram: add maxSendQueueSize socket option dgram: add maxSendQueueSize socket option Jan 25, 2017
@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 25, 2017

Removed the WIP from this. Added tests and docs. Also moved from an underscored property to a symbol.

@Trott Trott removed the wip Issues and PRs that are still a work in progress. label Jan 26, 2017
@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 26, 2017

ping @nodejs/collaborators

@bnoordhuis
Copy link
Member

The technical side looks fine to me but I don't know if I agree it's the best approach. A hard limit that is an error to hit is rather inflexible.

Strawman counterproposal: what if .send() and .sendto() indicated whether the data was sent or queued so the caller could act accordingly?

@mcollina
Copy link
Member

@bnoordhuis I think implementing backpressure for a dgram socket is not a good idea because it creates too much similarity between dgram and net, and there is already too much. TCP and UDP are two different things, and UDP does not implement any type of flow control.
This is error is only relevant during the "deferred open" scenario.

@cjihrig I do not like the error either. I think we should just call the callback with an error, and only if a callback is not present emit('error') on the whole socket.

BTW, I think we should set this default value to an arbitrary number like 65536, or maybe maintaining the actual length in bytes of the queue, and set it to some amount of MB. That would be a separate change with semver-major.

@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 27, 2017

I took a stab at a different approach in cjihrig@015e3f9, which doesn't expose the implementation detail that there is a queue at all. PTAL

In the current situation, DNS failures had no effect on the queue (we were only handling listening events). This was a problem in the deferred situation where the user also ignores the error events that are emitted. I fixed the problem by destroying the queue if an error occurs during the initial DNS lookup. I think it's a fair tradeoff that if the socket cannot bind then no data is queued and sent.

@mcollina
Copy link
Member

@cjihrig I like the second solution much more, and it is inline with how UDP works. 👍

self.emit('error', new Error('Maximum send queue size exceeded'));
return;
}

self._queue.push(toEnqueue);
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its safe to remove this.

@cjihrig
Copy link
Contributor Author

cjihrig commented Jan 27, 2017

@mcollina second approach implemented in #11036. Closing this one.

@cjihrig cjihrig closed this Jan 27, 2017
@cjihrig cjihrig deleted the dgram branch January 27, 2017 19:48
cjihrig added a commit to cjihrig/node that referenced this pull request Jan 30, 2017
When send() triggers an implicit bind, the send operation is
added to an internal queue. If a DNS error occurs during the bind,
there is currently no mechanism for clearing the queue other than
sending more data. If DNS errors keep occurring, the queue will
continue to grow with no upper bound. This commit reports errors
with implicit binds, and clears the queue. This should be fine,
given the nature of UDP.

Refs: nodejs/node-v0.x-archive#8705
Refs: nodejs#10902
PR-URL: nodejs#11036
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dgram Issues and PRs related to the dgram subsystem / UDP. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants