Inter-Driver Communications

When possible, drivers should stand alone and not rely on the presence or version of a neighboring driver that is running next to it in the system. Drivers that interact with each other through shared dependencies are prone to assembly version mismatch and other factors outside of the driver's control. Dependency assemblies should also be avoided if possible. Tools like ILMerge can help with avoiding dependency assemblies in some cases.

However, in some cases, dependencies cannot be avoided. At the same time, some control system programs may choose to load drivers in separate processes or application domains. This could break a system that relies on a shared dependency and access to a static singleton class.

Therefore, to support drivers that must be loaded in the same process or application domain as neighboring drivers, each shared driver must specify a DependencyGroup in their data file. Drivers with the same DependencyGroup string must be loaded by the application into the same process or domain.

NOTE: Drivers that share a DependencyGroup but have different versions of an assembly with the same name cannot be simultaneously loaded into the same process. Because of this, drivers using the same DependencyGroup must also keep versions of their shared assemblies in sync. To avoid this versioning issue, the contents of the shared assembly should be kept to a minimum and be designed generically to support future functionality without having to revise the shared assembly.

If a driver does not have any dependencies, it should specify an empty string as its DependencyGroup. This informs the application explicitly that a dependency does not exist.

Drivers that predate the existence of DependencyGroup may have a group filled in on the driver portal to support continued operation. However, when one of these drivers are sideloaded and no information is available on the driver portal, the application will see DependencyGroup as null. The application must then assume that the driver may have shared dependencies. Because of this scenario, it is important that the driver without dependencies specifies an empty string explicitly (rather than null) to clarify to the application that no DependencyGroup is applicable.

Crestron Home OS Driver Hot-Swapping

Crestron Home® OS has started to support hosting drivers in alternate processes to enhance system stability and to allow drivers and their dependencies to be isolated. One enhancement of this implementation is that drivers can now be "hot-swapped" without requiring a restart of Crestron Home.

Because the drivers are hosted in separate processes, it is critical that the DependencyGroup for each driver is populated correctly. To provide additional background, refer to the following description of the logic that is applied to determine how a driver is hosted.

The rules defining how drivers are grouped in a host together derive from the following basic constraints:

  • Two versions of the same assembly cannot be loaded in the same process because of how the .NET framework works.
  • Certain drivers depend on shared static data and must run together in the same process.

With these constraints in mind, the smallest possible number of processes are used by Crestron Home to minimize overhead. However, when a driver swap occurs during runtime, keeping drivers online is prioritized over potentially restarting them all in a single new process, which may result in adding an additional process.

Additionally, Crestron Home does not yet support all device types running in a separate process, so any drivers that depend on being in the same process (with a shared DependencyGroup) are excluded from hot-swapping for now. In a future release, drivers that share a DependencyGroup will all be shut down and moved to a new process together when one is hot-swapped.

Based on the above, the current logic for hot-swapping is as follows:

  • When a driver is started:
    • If it has a DependencyGroup, it is started in the previously‑existing manner and excluded from the hot-swap feature.
      • In a future release, this will be replaced with logic that will find the correct existing host or that will determine which drivers must be stopped and restarted to have a valid host that can group the drivers.
    • The first suitable driver host process is selected to load the driver.
      • When a driver is assigned to a driver host, all AssemblyName and Version combinations from inside that package are registered as "used" in that host.
      • When checking whether a new driver can be loaded in that host, the new driver's assemblies and versions are cross-referenced with those that the process has already seen. If any assemblies have already been loaded but have different versions, that host is not suitable for loading the new driver.
      • This check takes precedence over DependencyGroup. Drivers with the same DependencyGroup that try to load different versions of the same assembly will still end up in separate processes. Because of this, separate dependency assemblies should be avoided where practical, either by combining the source or using tools such as ILMerge.
    • If there are no suitable processes to load the driver, a new process is created to load it.
  • When a driver is stopped:
    • If it is the last driver is the host process, the host process is shut down.
  • When a driver is hot-swapped:
    • Crestron Home tracks that the driver was swapped and assumes that even if it was swapped for the same assembly version, that version is actually different and should be isolated. This logic is implemented so that developer can recompile the same version during development and upload it again without having to update the version numbers. This feature is currently in development and has not yet been released in a beta version of the SDK.

When Crestron Home restarts, this logic is applied again. This means that the process allocation may be different, since after the restart, there will be no active processes that have previously loaded a particular assembly and version.

For example, if five drivers are in the system within a single process at system startup (following the rules above), and one is hot-swapped to a new version, this could result in two processes (the original four drivers in Host01 and the swapped driver in Host02). However, at the next restart, the new single host would be able to load all five drivers again since it never loaded v1 of the driver that was swapped.