close.go

 1package experimental
 2
 3import (
 4	"context"
 5
 6	"github.com/tetratelabs/wazero/internal/expctxkeys"
 7)
 8
 9// CloseNotifier is a notification hook, invoked when a module is closed.
10//
11// Note: This is experimental progress towards #1197, and likely to change. Do
12// not expose this in shared libraries as it can cause version locks.
13type CloseNotifier interface {
14	// CloseNotify is a notification that occurs *before* an api.Module is
15	// closed. `exitCode` is zero on success or in the case there was no exit
16	// code.
17	//
18	// Notes:
19	//   - This does not return an error because the module will be closed
20	//     unconditionally.
21	//   - Do not panic from this function as it doing so could cause resource
22	//     leaks.
23	//   - While this is only called once per module, if configured for
24	//     multiple modules, it will be called for each, e.g. on runtime close.
25	CloseNotify(ctx context.Context, exitCode uint32)
26}
27
28// ^-- Note: This might need to be a part of the listener or become a part of
29// host state implementation. For example, if this is used to implement state
30// cleanup for host modules, possibly something like below would be better, as
31// it could be implemented in a way that allows concurrent module use.
32//
33//	// key is like a context key, stateFactory is invoked per instantiate and
34//	// is associated with the key (exposed as `Module.State` similar to go
35//	// context). Using a key is better than the module name because we can
36//	// de-dupe it for host modules that can be instantiated into different
37//	// names. Also, you can make the key package private.
38//	HostModuleBuilder.WithState(key any, stateFactory func() Cleanup)`
39//
40// Such a design could work to isolate state only needed for wasip1, for
41// example the dirent cache. However, if end users use this for different
42// things, we may need separate designs.
43//
44// In summary, the purpose of this iteration is to identify projects that
45// would use something like this, and then we can figure out which way it
46// should go.
47
48// CloseNotifyFunc is a convenience for defining inlining a CloseNotifier.
49type CloseNotifyFunc func(ctx context.Context, exitCode uint32)
50
51// CloseNotify implements CloseNotifier.CloseNotify.
52func (f CloseNotifyFunc) CloseNotify(ctx context.Context, exitCode uint32) {
53	f(ctx, exitCode)
54}
55
56// WithCloseNotifier registers the given CloseNotifier into the given
57// context.Context.
58func WithCloseNotifier(ctx context.Context, notifier CloseNotifier) context.Context {
59	if notifier != nil {
60		return context.WithValue(ctx, expctxkeys.CloseNotifierKey{}, notifier)
61	}
62	return ctx
63}