Skip to content

Unify Provisioner implementation synchronization semantics #4

Description

@comps

Currently, each Provisioner uses very different synchronization approaches:

  • TestingFarmProvisioner has daemon=True threads that silently die in the background even after .stop()
  • SharedVirtProvisioner has one non-daemon thread with proper threading.Event waiting, but has very over-complicated creation/joining of the one thread (via a threading.Semaphore) depending on when it is / is not needed, to prevent (well, limit) race conditions with its use
  • PodmanProvisioner just uses a threading.Condition and creates containers inside .get_remote(), not in any background thread
  • TempVirtProvisioner combines threading.Event with threading.Condition and a collections.deque for the thread returns

It would be great to at least converge on some common fool-proof solution for all/most of these.

For example:

  1. Standard daemon=False threads with threading.Event propagation to lower-level functions, to be done ie. in testingfarm/api.py
  2. threading.Condition to be always used for synchronization (as a generic lock and also .wait_for()), to allow .stop() waking up a blocking .get_remote() across all implementations
    • (also .stop() on .get_remote() should always be an exception, not a random None from a blocking call)
  3. A simple FIFO collections.deque for passing returns/exceptions from threads, in combination with the threading.Condition

Not all provisioners need to use all these, but it also shouldn't be some random threading.Semaphore coupled to the logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions