1
0
mirror of https://github.com/lxc/incus.git synced 2026-02-05 09:46:19 +01:00

incusd/operations: Prevent concurrent access to metadata

Closes #2865

Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
This commit is contained in:
Stéphane Graber
2026-02-04 17:10:33 +01:00
parent b234ba988c
commit bb6e2b09eb

View File

@@ -153,6 +153,7 @@ func OperationCreate(s *state.State, projectName string, opClass OperationClass,
op.SetEventServer(s.Events)
}
// Validate and make a copy of the metadata to avoid concurrent reads/writes.
newMetadata, err := parseMetadata(opMetadata)
if err != nil {
return nil, err
@@ -506,7 +507,7 @@ func (op *Operation) Render() (string, *api.Operation, error) {
op.lock.Lock()
// Make a copy of the metadata to avoid concurrent reads/writes.
// Make a read-only copy of the metadata to avoid concurrent reads/writes.
metadata := map[string]any{}
for k, v := range op.metadata {
metadata[k] = v
@@ -592,6 +593,7 @@ func (op *Operation) UpdateMetadata(opMetadata any) error {
return errors.New("Read-only operations can't be updated")
}
// Validate and make a copy of the metadata to avoid concurrent reads/writes.
newMetadata, err := parseMetadata(opMetadata)
if err != nil {
return err
@@ -635,7 +637,6 @@ func (op *Operation) ExtendMetadata(metadata any) error {
// Get current metadata.
newMetadata := op.metadata
op.lock.Unlock()
// Merge with current one.
if op.metadata == nil {
@@ -645,7 +646,6 @@ func (op *Operation) ExtendMetadata(metadata any) error {
}
// Update the operation.
op.lock.Lock()
op.updatedAt = time.Now()
op.metadata = newMetadata
op.lock.Unlock()
@@ -665,9 +665,18 @@ func (op *Operation) ID() string {
return op.id
}
// Metadata returns the operation Metadata.
// Metadata returns a read-only copy of the operation metadata.
func (op *Operation) Metadata() map[string]any {
return op.metadata
op.lock.Lock()
defer op.lock.Unlock()
// Make a read-only copy of the metadata to avoid concurrent reads/writes.
metadata := map[string]any{}
for k, v := range op.metadata {
metadata[k] = v
}
return metadata
}
// URL returns the operation URL.