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

add syscall.abandonExport() #4951

Closed
warner opened this issue Mar 29, 2022 · 0 comments · Fixed by #4957
Closed

add syscall.abandonExport() #4951

warner opened this issue Mar 29, 2022 · 0 comments · Fixed by #4957
Assignees
Labels
enhancement New feature or request SwingSet package: SwingSet
Milestone

Comments

@warner
Copy link
Member

warner commented Mar 29, 2022

What is the Problem Being Solved?

When a vat is being upgraded, we preserve its durable exports (instances of a kind defined with defineDurableKind()), but we do not preserve the merely-virtual exports (defined with defineKind()).

By "not preserve", we mean that other (importing) vats will see the object become broken, just as if the vat had been terminated. If they send a message to this object, their result promise will be rejected.

Note that we're preserving the identity of the dead object. The kernel object table will continue to have an entry for it (however the owner field will be set to null). The importing vat c-lists will retain their entries. Only the exporting vat's c-list will be modifed, removing both the koNN -> o+NN/etc and the o+NN/etc -> koNN mappings.

We've talked in the past about making dead objects "taboo", revoking their identity entirely. We're not doing that now. If were, we'd also need a dispatch.abandonImport() call, to notify importing vats that their import has been removed from the c-list (therefore they must not reference it in outbound messages ever again).

The syscall name is a slight deviation from our existing naming scheme, but only in emphasis. From the vat's point of view, we have three messages that deal with imports:

  • syscall.dropImport() : "Hey kernel, you know that thing I was importing? Well, I can no longer reach it, so don't keep it alive for my sake. I'll never mention it in a message again, but it might still be used as the key of a WeakMap/WeakSet, so let's keep it in the c-list for now."
  • syscall.retireImport(): "Hey kernel, you know that thing I dropped? I no longer have any WeakMaps/WeakSets that are keyed by it (because I deleted the last one, or never had any in the first place), so let's delete it from our shared c-list.
  • dispatch.retireImport(): "Hey vat, you know that import that you dropped (with syscall.dropImport)? Everybody else dropped it too, even the exporting vat stopped its internal references, so the object is completely gone. Please delete any WeakMap/WeakSet entries that were keyed by it. I'm deleting it from our shared c-list now. You'll never hear about it again (until/unless it gets re-introduced in some new message).

And we have three messages (now four) that deal with exports:

  • dispatch.dropExport(): "Hey vat, you know that object you exported earlier? Everybody else dropped it. Don't keep it alive for our sake. I'll never mention it in an inbound dispatch.deliver or dispatch.notify again. However those other vats might still be using it as the key of a WeakMap/WeakSet, so please let me know if/when you delete it. I'm leaving it in our shared c-list for now.
  • dispatch.retireExport(): "Hey vat, you know that object we dropped earlier? Well, no other vat is using it as a WeakMap/WeakSet key, so we don't need the identity any more. I'm deleting it from our shared c-list. Don't tell us if if/when you delete it, we no longer care."
  • syscall.retireExport(): "Hey kernel, you know that object you dropped earlier? I deleted it. Tell all other vats (with dispatch.retireImport) to delete any WeakMap/WeakSet entries that were keyed by it, and delete it from our shared c-list. I'll never mention it again (until it gets re-exported in some new message).
  • NEW syscall.abandonExport() (would be syscall.dropExport but with more emphasis): "Hey kernel, you know that object I exported earlier? I know everybody is still referencing it, but I don't love it anymore, so I'm going to forget about it. Delete it from our shared c-list. If anybody else tries to talk to it, give them an error. We will never mention it again (and it won't ever be re-introduced because I'm forgetting about it entirely, even from my virtualized data, and my allocation counters won't ever re-use the ID either).

If/when we destroy the object's identity, we'd use dispatch.abandonImport to signal the importing vats about the c-list deletion. But we're not doing that now.

Because we don't currently have any way to send importing vats a notification that their import has stopped working, they'll only find out if/when they try to send a message to it.

Description of the Design

Add syscall.abandonExports(vrefs).

The kernel will react by:

  • mapping all vrefs to krefs (vat-fatal error if the vref was not in the c-list, or if it was not an object export o+...)
  • clear the owner field in the kernel object table (set it to null)
  • delete both entries from the calling vat's c-list

We need to confirm that the kernel object entry remains present until all other references are dropped. I think we already do this w.r.t. terminated vats, but we should double-check. The gcAction that wants to send dispatch.dropExport to the owning vat must tolerate that owner being empty.

Security Considerations

None I can think of.

Note that userspace will not get access to this. It will only be used by liveslots during dispatch.stopVat().

Some day, we might define a revocation authority at the time the object is created, in which case the userspace code that created an object might also be allowed to destroy it.

Test Plan

Unit tests must confirm that the c-list entries are deleted, the kernel object table owner is cleared, and any external refcounts remain unchanged. It should also confirm that GC can still take place when the last importing vat retires their import, and that we don't have any GC actions sent to the exporting vat.

We should also test that an object in the merely-recognizable state can be abandoned properly. In this case, the exporting vat will see dispatch.dropExport, then dispatch.stopVat, and will emit syscall.abandonExport during the stopVat delivery.

refs #1848 (needed to delete leftover non-durable exports)

@warner warner added enhancement New feature or request SwingSet package: SwingSet labels Mar 29, 2022
@warner warner self-assigned this Mar 29, 2022
warner added a commit that referenced this issue Mar 30, 2022
This allows liveslots to abandon a previously-exported object. The
kernel marks the object as orphaned (just as if the exporting vat was
terminated), and deletes the exporter's c-list entry. All importing
vats continue to have the same access as before, and the refcounts are
unchanged.

Liveslots will use this during `stopVat()` to revoke all the
non-durable objects that it had exported, since these objects won't
survive the upgrade. The vat version being stopped may still have a
Remotable or a virtual form of the export, so userspace must not be
allowed to execute after this syscall is used, otherwise it might try
to mention the export again, which would allocate a new mismatched
kref, causing confusion and storage leaks.

Our naming scheme would normally call this `syscall.dropExports`
rather than `syscall.abandonExports`, but I figured this is
sufficiently unusual that it deserved a more emphatic name. Vat
exports are an obligation, and this syscall allows a vat to shirk that
obligation.

closes #4951
refs #1848
warner added a commit that referenced this issue Mar 30, 2022
This allows liveslots to abandon a previously-exported object. The
kernel marks the object as orphaned (just as if the exporting vat was
terminated), and deletes the exporter's c-list entry. All importing
vats continue to have the same access as before, and the refcounts are
unchanged.

Liveslots will use this during `stopVat()` to revoke all the
non-durable objects that it had exported, since these objects won't
survive the upgrade. The vat version being stopped may still have a
Remotable or a virtual form of the export, so userspace must not be
allowed to execute after this syscall is used, otherwise it might try
to mention the export again, which would allocate a new mismatched
kref, causing confusion and storage leaks.

Our naming scheme would normally call this `syscall.dropExports`
rather than `syscall.abandonExports`, but I figured this is
sufficiently unusual that it deserved a more emphatic name. Vat
exports are an obligation, and this syscall allows a vat to shirk that
obligation.

closes #4951
refs #1848
warner added a commit that referenced this issue Mar 30, 2022
This allows liveslots to abandon a previously-exported object. The
kernel marks the object as orphaned (just as if the exporting vat was
terminated), and deletes the exporter's c-list entry. All importing
vats continue to have the same access as before, and the refcounts are
unchanged.

Liveslots will use this during `stopVat()` to revoke all the
non-durable objects that it had exported, since these objects won't
survive the upgrade. The vat version being stopped may still have a
Remotable or a virtual form of the export, so userspace must not be
allowed to execute after this syscall is used, otherwise it might try
to mention the export again, which would allocate a new mismatched
kref, causing confusion and storage leaks.

Our naming scheme would normally call this `syscall.dropExports`
rather than `syscall.abandonExports`, but I figured this is
sufficiently unusual that it deserved a more emphatic name. Vat
exports are an obligation, and this syscall allows a vat to shirk that
obligation.

closes #4951
refs #1848
warner added a commit that referenced this issue Mar 30, 2022
This allows liveslots to abandon a previously-exported object. The
kernel marks the object as orphaned (just as if the exporting vat was
terminated), and deletes the exporter's c-list entry. All importing
vats continue to have the same access as before, and the refcounts are
unchanged.

Liveslots will use this during `stopVat()` to revoke all the
non-durable objects that it had exported, since these objects won't
survive the upgrade. The vat version being stopped may still have a
Remotable or a virtual form of the export, so userspace must not be
allowed to execute after this syscall is used, otherwise it might try
to mention the export again, which would allocate a new mismatched
kref, causing confusion and storage leaks.

Our naming scheme would normally call this `syscall.dropExports`
rather than `syscall.abandonExports`, but I figured this is
sufficiently unusual that it deserved a more emphatic name. Vat
exports are an obligation, and this syscall allows a vat to shirk that
obligation.

closes #4951
refs #1848
warner added a commit that referenced this issue Mar 31, 2022
This allows liveslots to abandon a previously-exported object. The
kernel marks the object as orphaned (just as if the exporting vat was
terminated), and deletes the exporter's c-list entry. All importing
vats continue to have the same access as before, and the refcounts are
unchanged.

Liveslots will use this during `stopVat()` to revoke all the
non-durable objects that it had exported, since these objects won't
survive the upgrade. The vat version being stopped may still have a
Remotable or a virtual form of the export, so userspace must not be
allowed to execute after this syscall is used, otherwise it might try
to mention the export again, which would allocate a new mismatched
kref, causing confusion and storage leaks.

Our naming scheme would normally call this `syscall.dropExports`
rather than `syscall.abandonExports`, but I figured this is
sufficiently unusual that it deserved a more emphatic name. Vat
exports are an obligation, and this syscall allows a vat to shirk that
obligation.

closes #4951
refs #1848
warner added a commit that referenced this issue Mar 31, 2022
This allows liveslots to abandon a previously-exported object. The
kernel marks the object as orphaned (just as if the exporting vat was
terminated), and deletes the exporter's c-list entry. All importing
vats continue to have the same access as before, and the refcounts are
unchanged.

Liveslots will use this during `stopVat()` to revoke all the
non-durable objects that it had exported, since these objects won't
survive the upgrade. The vat version being stopped may still have a
Remotable or a virtual form of the export, so userspace must not be
allowed to execute after this syscall is used, otherwise it might try
to mention the export again, which would allocate a new mismatched
kref, causing confusion and storage leaks.

Our naming scheme would normally call this `syscall.dropExports`
rather than `syscall.abandonExports`, but I figured this is
sufficiently unusual that it deserved a more emphatic name. Vat
exports are an obligation, and this syscall allows a vat to shirk that
obligation.

closes #4951
refs #1848
@mergify mergify bot closed this as completed in #4957 Mar 31, 2022
@Tartuffo Tartuffo added this to the Mainnet 1 milestone Apr 5, 2022
warner added a commit that referenced this issue Dec 23, 2023
This clause was commented out because bug #3378 was still pending at
the time. I think we happened to fix that as a side-effect of adding
`syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we
could re-enable the clause.

closes #3378
warner added a commit that referenced this issue Dec 23, 2023
This clause was commented out because bug #3378 was still pending at
the time. I think we happened to fix that as a side-effect of adding
`syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we
could re-enable the clause.

closes #3378
warner added a commit that referenced this issue Jun 14, 2024
This clause was commented out because bug #3378 was still pending at
the time. I think we happened to fix that as a side-effect of adding
`syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we
could re-enable the clause.

closes #3378
warner added a commit that referenced this issue Jun 14, 2024
This clause was commented out because bug #3378 was still pending at
the time. I think we happened to fix that as a side-effect of adding
`syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we
could re-enable the clause.

closes #3378
mergify bot added a commit that referenced this issue Jun 14, 2024
This clause was commented out because bug #3378 was still pending at the time. I think we happened to fix that as a side-effect of adding `syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we could re-enable the clause.

closes #3378
mhofman pushed a commit that referenced this issue Jun 20, 2024
This clause was commented out because bug #3378 was still pending at
the time. I think we happened to fix that as a side-effect of adding
`syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we
could re-enable the clause.

closes #3378
mhofman pushed a commit that referenced this issue Jun 20, 2024
This clause was commented out because bug #3378 was still pending at the time. I think we happened to fix that as a side-effect of adding `syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we could re-enable the clause.

closes #3378
mhofman pushed a commit that referenced this issue Jun 22, 2024
This clause was commented out because bug #3378 was still pending at
the time. I think we happened to fix that as a side-effect of adding
`syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we
could re-enable the clause.

closes #3378
mhofman pushed a commit that referenced this issue Jun 22, 2024
This clause was commented out because bug #3378 was still pending at the time. I think we happened to fix that as a side-effect of adding `syscall.abandonExport` for #4951 (in PR #4957), but didn't realize we could re-enable the clause.

closes #3378
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request SwingSet package: SwingSet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants