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

proposal: syscall: ReleaseCallback for Windows #46184

Closed
hajimehoshi opened this issue May 15, 2021 · 16 comments
Closed

proposal: syscall: ReleaseCallback for Windows #46184

hajimehoshi opened this issue May 15, 2021 · 16 comments

Comments

@hajimehoshi
Copy link
Member

hajimehoshi commented May 15, 2021

Now a callback generated by syscall.NewCallback or syscall.NewCallbackCDecl is never released based on the current implementation (especially runtime/syscall_windows.go).

My understanding is that it is hard or impossible to release them automatically. Would it be possible to have a function to release a callback like ReleaseCallback? Or, what about changing the return type of NewCallback to a new type Callback and letting it have Release function?

CC @mknyszek

@gopherbot gopherbot added this to the Proposal milestone May 15, 2021
@networkimprov
Copy link

cc @alexbrainman @mattn @zx2c4

@gopherbot add OS-Windows

@ianlancetaylor
Copy link
Contributor

What should happen if a released callback is called?

@hajimehoshi
Copy link
Member Author

Just panic, maybe? This should be the same situation as calling a released syscall/js.Func.

@alexbrainman
Copy link
Member

@hajimehoshi

Why do you need new syscall.ReleaseCallback function? What would you be able to do that you cannot do now?

I don't see any use for syscall.ReleaseCallback.

Thank you.

Alex

@hajimehoshi
Copy link
Member Author

hajimehoshi commented May 17, 2021

My understanding is that there is a limit for the number of the callbacks. If the number of calls of NewCallback reaches the limit, you can no longer create a new callback. Is that correct?

Or, at least, I'd want the documentation to make it explicit that a callback created by NewCallback is never released.

@hajimehoshi
Copy link
Member Author

Actual example is waveOutOpen. This takes a callback each time when an audio stream is opened. If I didn't consider the limitation of NewCallback(CDecl), I would run into the issue of the limitation. So, I wanted a function to release the callback so that I could release it the audio stream ends, or I wanted to know the limitation so that I could avoid the limitation by reusing the same callback.

@zx2c4
Copy link
Contributor

zx2c4 commented May 17, 2021

You're best off having one global callback for that, and using the dwInstance field in order to index into a map of actual callbacks.

(Alternatively, that function takes an event handle instead.)

@mknyszek
Copy link
Contributor

I agree that NewCallback should document its limitations (I'll write up a CL for that soon if nobody beats me to it), but I think there are problems with something like ReleaseCallback. Like, if the callback is passed deep into a library, especially one that can trigger the callback asynchronously, the failure mode of releasing the callback without "de-registering" it is that either:

  1. The slot is empty, and the callback attempts to jump to nil and crashes (that's fine), or
  2. The slot is reused, and the callback calls into something totally unrelated.

(2) Is the case I'm worried about, because we can't really detect it and panic, at least not the way callbacks are implemented today. There might be some way to work around this, though. The limitation today stems from the fact that we identify the slot based on the return PC passed into callbackasm1, I'm not sure how else we can signal which callback we should use while still going down a single common path through the runtime to set up all the Go scheduler things that need to happen on the potentially external thread.

@alexbrainman
Copy link
Member

Actual example is waveOutOpen. This takes a callback each time when an audio stream is opened.

I would do what @zx2c4 suggested in #46184 (comment). I think one callback function should be enough in your scenario.

I also share @ianlancetaylor (#46184 (comment)) and @mknyszek (#46184 (comment)) concerns. There is no general way to inform external code to stop calling your callback function before you release it. This will cause memory corruption and crashes. It is not worth the trouble.

Alex

@gopherbot
Copy link

Change https://golang.org/cl/321133 mentions this issue: syscall: document NewCallback and NewCallbackCDecl limitations

@hajimehoshi
Copy link
Member Author

There is no general way to inform external code to stop calling your callback function before you release it. This will cause memory corruption and crashes. It is not worth the trouble.

I think this is the same situation as syscall/js.Func's Release, and if we had ReleaseCallback, using this should be the user's responsibility.

Based on #46184 (comment), I'm now convinced that implementing ReleaseCallback would be difficult: calling a released callback cannot panic safely.

@rsc rsc moved this from Incoming to Active in Proposals (old) May 19, 2021
@rsc
Copy link
Contributor

rsc commented May 19, 2021

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

gopherbot pushed a commit that referenced this issue May 20, 2021
Currently NewCallback and NewCallbackCDecl may only be called a limited
number of times in a single Go process, but this property of the API is
not documented. This change fixes that, but does not document the
precise limit to avoid making that limit part of the API, leaving us
open to increasing or decreasing the limit in the future as needed.

Although the API avoids documenting a limit, it does guarantee a minimum
callback count so users can rely on at least some amount of callbacks
working.

Updates #46184.

Change-Id: I5129bf5fe301efff73ac112ba1f207ab32058833
Reviewed-on: https://go-review.googlesource.com/c/go/+/321133
Trust: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
@rsc rsc changed the title proposal: syscall: ReleaseCallback for Windows proposal: syscall: ReleaseCallback for Windows May 26, 2021
@rsc
Copy link
Contributor

rsc commented May 26, 2021

Based on #46184 (comment), I'm now convinced that implementing ReleaseCallback would be difficult: calling a released callback cannot panic safely.

So it sounds like we should not add ReleaseCallback then?

@hajimehoshi
Copy link
Member Author

I don't think we should not, but I'm not sure how feasible this would be. @mknyszek what do you think?

@rsc
Copy link
Contributor

rsc commented Jun 2, 2021

Based on the discussion above, this proposal seems like a likely decline.
— rsc for the proposal review group

@rsc rsc moved this from Active to Likely Decline in Proposals (old) Jun 2, 2021
@rsc rsc moved this from Likely Decline to Declined in Proposals (old) Jun 9, 2021
@rsc
Copy link
Contributor

rsc commented Jun 9, 2021

No change in consensus, so declined.
— rsc for the proposal review group

@golang golang locked and limited conversation to collaborators Jun 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

No branches or pull requests

8 participants