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

maybe have kernel retain vatParameters, to enable kernel-unilateral vat upgrade #8947

Closed
warner opened this issue Feb 20, 2024 · 2 comments · Fixed by #10270
Closed

maybe have kernel retain vatParameters, to enable kernel-unilateral vat upgrade #8947

warner opened this issue Feb 20, 2024 · 2 comments · Fixed by #10270
Assignees
Labels
enhancement New feature or request SwingSet package: SwingSet

Comments

@warner
Copy link
Member

warner commented Feb 20, 2024

What is the Problem Being Solved?

One task identified as a requirement for a kernel-unilateral restart-all-vats feature is to have the kernel retain each vat's vatParameters.

vatParameters is a chunk of data (passable object graph, except Promises are forbidden) which is provided as the second argument to the vat's buildRootObject() function at vat startup time. It is meant to parameterize the vat bundle for some specific purpose (making it distinct from all other vats using the same bundle). By providing these parameters early, before any messages have arrived, the vat bundle can use them when (re-)defining its Kinds.

Currently, the kernel treats vatParameters more like a message. In particular, the kernel does not remember the data after vat startup. vatParameters are held in the run-queue startVat event record, which is dropped after the delivery is begun. Any any object krefs in the vP are held with a refcount until they leave the queue, after which (if nothing else is holding onto them) they may get garbage collected.

(The same is true of vat root objects: once the bootstrap message is delivered, the kernel does not retain a reference to them, and the objects may get collected if the bootstrap vat did not choose to hold onto them. The policy I chose was to have the kernel defer to userspace decisions about what is important to retain and what is important to collect).

However, we can't correctly restart a vat without its vatParameters, and if the kernel is going to unilaterally restart vats, we need to keep them around.

Description of the Design

We'll put a copy of the vatParameterCapData (or "vpcd" for short) into the kvStore vNN.options record, or perhaps in a new vNN.vatParameterCapData record.

When userspace creates a vat (via vat-admin), the kernel will store a copy of the vpcd, and increment the refcounts on any objects. When userspace upgrades a vat (supplying new vatParameters), the kernel will retrieve the old data, store the new data, increment the refcounts on the new data, then decrement the refcounts on the old data. When the vat is terminated, the refcounts will be decremented.

We'll continue to put a copy of the vatParameterCapData in the startVat message, and increment the refcount when doing so, and decrement the refcount when delivering startVat, to avoid upgrade concerns about refcount skew. However the startVat-time decref will never allow an object to be freed, because all such objects will also have a refcount for the kvStore copy.

Security Considerations

None I can think of. Userspace cannot use this feature to retain objects any longer than it could have without it.

Scaling Considerations

This causes all vatParameter objects to be held uncollectable until userspace upgrades the vat with different objects, or the vat is terminated. This is unlikely to represent a significant memory "leak", both because of the low rate of upgrade, and because (at least traditionally) most objects passed to vatParameters are used and held by the userspace code for the entire incarnation.

Test Plan

Unit tests on the kernel side, in the code that checks refcounts.

Upgrade Considerations

Current vats do not have any retained vpcd, and cannot retrieve it from the kvStore contents. So we need code to recognize that a vat does not currently have this data, and make it ineligible for unilateral upgrade.

@warner
Copy link
Member Author

warner commented Jun 5, 2024

Another decision to be made: when E(adminNode).upgrade() is called without a vatParameters option, should that mean "use the old vatParameters", or should (as it does now) mean "vatParameters = {}" ?

The #8405 "upgrade all vats" command will always use each vat's old vatParameters, as there's no place to put replacements (even if we were willing to take an option with one property for each of our 100+ vats, the upgrade-all-vats call will happen from outside the kernel, so it cannot accept slots / object references).

I'm kind of inclined to have it mean "use the old vatParameters". I think we'd need some vat-vat-admin changes to accomplish that, to tell the kernel whether the option was undefined or {}.

warner added a commit that referenced this issue Oct 13, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(vatAdminSvc).upgradeVat()`.

When received via `createVat()` or `upgradeVat()`, the vatParameters
can contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgradeVat()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

fixes #8947
@warner
Copy link
Member Author

warner commented Oct 13, 2024

I've got a PR to retain the parameters, and to provide an internal interface (vatKeeper.getVatParameters()) to fetch them. I haven't yet made any changes to the way vat upgrade works, so I'll create a separate ticket for that task: #10271

While testing, I noticed that we're already retaining all the vat-parameter krefs anyways, because they are sent through device-vatAdmin, and devices don't do GC. So that device will hold on to everything it was given, forever, and that happens to include the vatParameter krefs. I did a quick survey of mainnet state, and it's currently holding onto 21 objects. I saw ZoeService in the list, and some number of Zoe Invitation issuer things.

warner added a commit that referenced this issue Oct 13, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgradeVat()`.

When received via `createVat()` or `upgradeVat()`, the vatParameters
can contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgradeVat()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

fixes #8947
warner added a commit that referenced this issue Oct 13, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgrade()`.

When received via `createVat()` or `upgrade()`, the vatParameters can
contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgrade()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

fixes #8947
warner added a commit that referenced this issue Oct 26, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgrade()`.

When received via `createVat()` or `upgrade()`, the vatParameters can
contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgrade()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

fixes #8947
warner added a commit that referenced this issue Oct 26, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgrade()`.

When received via `createVat()` or `upgrade()`, the vatParameters can
contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgrade()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

The slow-termination test was updated: it counts kvStore entries
precisely as we delete them all, so it requires an update each time we
add one.

fixes #8947
warner added a commit that referenced this issue Oct 27, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgrade()`.

When received via `createVat()` or `upgrade()`, the vatParameters can
contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgrade()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

The slow-termination test was updated: it counts kvStore entries
precisely as we delete them all, so it requires an update each time we
add one.

fixes #8947
warner added a commit that referenced this issue Oct 27, 2024
All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgrade()`.

When received via `createVat()` or `upgrade()`, the vatParameters can
contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgrade()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

The slow-termination test was updated: it counts kvStore entries
precisely as we delete them all, so it requires an update each time we
add one.

fixes #8947
@mergify mergify bot closed this as completed in #10270 Oct 27, 2024
mergify bot added a commit that referenced this issue Oct 27, 2024
)

fix(swingset): retain vatParameters for vat creation and upgrade

All vats have `vatParameters`, a mostly-arbitrary data record,
delivered as the second argument to their `buildRootObject()`
function. Dynamic vats get their vatParameters from the options bag
given to `E(vatAdminSvc).createVat()`. Static vats get them from the
kernel config record. When a vat is upgraded, the new incarnation gets
new vatParameters; these come from the options bag on
`E(adminNode).upgrade()`.

When received via `createVat()` or `upgrade()`, the vatParameters
can contain object and device references. VatParameters cannot include
promises.

Previously, the kernel delivered vatParameters to the vat, but did not
keep a copy. With this commit, the kernel retains a copy of
vatParameters (including a refcount on any kernel objects
therein). Internally, `vatKeeper.getVatParameters()` can be used to
retrieve this copy.  Only vats created or upgraded after this commit
lands will get retained vatParameters: for older vats this will return
`undefined`.

Retained vat parameters should make it easier to implement "upgrade
all vats", where the kernel perform a unilateral `upgrade()` on all
vats without userspace asking for it. When this is implemented, the
new incarnations will receive the same vatParameters as their
predecessors.

fixes #8947
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.

1 participant