Skip to content

Fixed task start race condition

Compare
Choose a tag to compare
@aleph2c aleph2c released this 26 Dec 21:18
· 29 commits to master since this release

When the start_at method is called, the statechart climbs into its initial state, then the active object starts a thread.

But, prior to this release, if the start_at method caused calls to other methods which needed a task to run, the task would be started to honor the request of the call. This meant that the task would be started too soon, and the active object could send events to the HSM dispatcher, while it was still trying to climb into its initial state. Statecharts only run one event at a time, and starting a chart while having it react to events breaks the RTC protocol meaning that the statechart could behave non-deterministically .

Specifically, the bug fixed in this release would happen when a call to subscribe, or publish, or post_fifo, or post_lifo where made during the start-up process. The start_thread_if_not_running decorator wrapped these calls so that they could work because they needed a thread to work. However it was a mistake to allow the thread to be started in more than one location in the code base. This bug has been fixed in this release and the start_thread_if_not_running decorator has been removed so that the same mistake won't be made again.

There are situations when the subscribe, or publish, or post_fifo, or post_lifo calls will be made before the thread is started. These requests must be honored but they can be deferred till after the thread is started. To grant the client access to these features without a running thread, the post_fifo and post_lifo calls put their requests directly into the Active Object's queues so that they will be acted upon when the thread is started. To do the same for the publish and subscribe calls, two new meta signals (a signal which carries another signal) were invented. If a publish method is called before a thread was started, an event with the signal named PUBLISH_META_SIGNAL is posted using the post_lifo technique into the Active Object's lifo queue. Inside of this event is enough information to publish an event with the required priority once the Active Object's thread started at a later time. A similar technique was followed to honor calls to subscribe, it's signal name is SUBSCRIBE_META_SIGNAL.

The ActiveObject's self.top state was overloaded to catch the PUBLISH_META_SIGNAL and SUBSCRIBE_META_SIGNAL and dispatch them to private functions which work once the thread is running. To improve performance the publish and subscribe methods only publish events if no thread is running. If the thread is running they call thread related private functions directly, as they did before.

In addition to this change, a subscribed method was added to the ActiveObject and ActiveFabric class. This method could be used to determine if a signal_name or event had been subscribed to for a given queue type (lifo/fifo).

Also, the stop_fabric and stop_active_object internal signals were renamed to STOP_FABRIC_SIGNAL and STOP_ACTIVE_OBJECT_SIGNAL to make their names consistent with other internal signal names.