-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Proposal: Callback based Signal API #11158
Comments
At the system call level, signals are exposed as interrupts so handling them as events makes so much more sense! |
Rather than using
|
But why do you think that is better than addEventListener? |
I generally like the proposal for |
Presumably we would always have our own signal event handlers and dispatch the events rather than lazy initialisation? We need to do that in order to support things like spin up inspector from |
My concern about this design is that how to unbind from the signal is not obvious. I can think of 3 different designs for unbinding, for example, and it seems difficult to decide which is better than the other. Deno.onSignal("SIGINT", handler)
Deno.unbindSignal("SIGINT", handler); // inspired by add/removeEventListener
const handleId = Deno.onSignal("SIGNAL", handler);
Deno.clearSignal(handleId); // inspired by clearTimeout
const cancel = Deno.onSignal("SIGNAL", handler);
cancel(); |
@bartlomieju I'm open to But personally I don't think mixing events to window.addEventListener = function addEventListener(type, listener, options) {
if (isSignalType(type)) {
addSignalHandler(type, listener, options);
} else {
EventTarget.prototype.addEventListner.call(globalThis, type, listener, options);
}
} With the above construction, signal related stuff can be separated into |
@kt3k That implementation would likely break some WPT once I fix up |
@lucacasonato Could you elaborate on that? What do you mean by conditional dispatch? |
I.e. an event is only dispatched if there is a listener. I vaguely remember the DOM spec saying that dispatchers should be unaware of the number of event listeners. Another issue is modifying the addEventListener method on |
In the light of Luca's argument I'm even more in favor of |
I don't know whether dom spec has such rules, but I doubt dom implementations dispatch
Do we need to support EventTarget side addEventLister(type, callback, options) {
...
const target = this ?? globalThis;
target[Symbol.for("Deno.addEventListenerHook")]?.(type, callback, options);
} window side window[Symbol.for("Deno.addEventListenerHook")] = function addSignalHandler(type, callback, options) { ... } |
I believe the section @lucacasonato is talking about is https://dom.spec.whatwg.org/#observing-event-listeners. It doesn't require that the presence or absence of listeners not be observable to the code dispatching the event, but it does say that adding an empty listener mustn't change the event's behavior, and it should only have an effect on performance if there's no reasonable alternative. And in this case, adding an empty listener would change the behavior, since it would prevent the default signal handler from running. But there is a way to make this work with the behavior required for DOM events: by requiring the listeners to call |
@andreubotella Thank you for the input.
This suggestion makes sense to me, but this sounds difficult to implement to me. We even can't restore the default behavior after unbinding from the signal at the moment (#7164). Now I'd prefer |
I updated the main description of the issue from |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. |
This proposal suggests removing the existing Signal APIs and instead suggests adding Callback based Signal APIs.
Suggested APIs
Note: This proposal originally suggested
globalThis.addEventListener("SIGINT", ...)
globalThis.removeEventListener("SIGINT", ...)
APIs, but I changed them to the above because of the concern about the side effect of attaching listeners. refs: #11158 (comment) #11158 (comment)Motivations
Currently we have AsyncIterable based API in the unstable namespace.
And optionally Promise based API.
These APIs are confusing to the users because of several reasons.
(1.) Because signal handlers use AsyncUnref Op internally, the runtime can exit in the middle of for-await loop without breaking it, and this is confusing.
The above example exits immediately without printing anything.
(2.) Similarly to (1.), the runtime can exit even when the promise is still in pending state. This behavior is confusing (There is no other promise APIs which works like this)
The above example exits immediately without printing anything.
(3.) One of the reasons to choose async iterable API design is that it can handle the back pressure effectively, but in the case of signals, it isn't used in such a way (A program isn't flooded by signals in general). So this reasoning doesn't apply to signal APIs.
Callback based API addresses these problems in a natural way
The above program exits immediately, but I think this doesn't cause any surprise to the users unlike async iterable based API.
The text was updated successfully, but these errors were encountered: