mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-09-24 23:31:36 +08:00
obs-scripting: Make callback "removed" variable atomic
Makes the callback variable "removed" atomic, and on script unload, first sets all callbacks to removed before actually unloading the script out of a safety precaution. (See note at the bottom for further details) This minimizes the possibility of a race condition where the script callback could be called while those callbacks were being removed. Big note for this change, this change should eventually be replaced with a reference counting ownership method where script callbacks can hold a reference and share ownership of the script if it's still alive while the script callback is being called. That way the script callbacks can safely execute. May require a fair amount of reworking of the script object.
This commit is contained in:
+29
-11
@@ -431,7 +431,7 @@ static void timer_call(struct script_callback *p_cb)
|
||||
{
|
||||
struct python_obs_callback *cb = (struct python_obs_callback *)p_cb;
|
||||
|
||||
if (p_cb->removed)
|
||||
if (script_callback_removed(p_cb))
|
||||
return;
|
||||
|
||||
lock_callback(cb);
|
||||
@@ -476,7 +476,7 @@ static void obs_python_tick_callback(void *priv, float seconds)
|
||||
{
|
||||
struct python_obs_callback *cb = priv;
|
||||
|
||||
if (cb->base.removed) {
|
||||
if (script_callback_removed(&cb->base)) {
|
||||
obs_remove_tick_callback(obs_python_tick_callback, cb);
|
||||
return;
|
||||
}
|
||||
@@ -546,7 +546,7 @@ static void calldata_signal_callback(void *priv, calldata_t *cd)
|
||||
{
|
||||
struct python_obs_callback *cb = priv;
|
||||
|
||||
if (cb->base.removed) {
|
||||
if (script_callback_removed(&cb->base)) {
|
||||
signal_handler_remove_current();
|
||||
return;
|
||||
}
|
||||
@@ -652,7 +652,7 @@ static void calldata_signal_callback_global(void *priv, const char *signal,
|
||||
{
|
||||
struct python_obs_callback *cb = priv;
|
||||
|
||||
if (cb->base.removed) {
|
||||
if (script_callback_removed(&cb->base)) {
|
||||
signal_handler_remove_current();
|
||||
return;
|
||||
}
|
||||
@@ -767,7 +767,7 @@ static void hotkey_pressed(void *p_cb, bool pressed)
|
||||
{
|
||||
struct python_obs_callback *cb = p_cb;
|
||||
|
||||
if (cb->base.removed)
|
||||
if (script_callback_removed(&cb->base))
|
||||
return;
|
||||
|
||||
lock_callback(cb);
|
||||
@@ -803,7 +803,7 @@ static void hotkey_callback(void *p_cb, obs_hotkey_id id, obs_hotkey_t *hotkey,
|
||||
{
|
||||
struct python_obs_callback *cb = p_cb;
|
||||
|
||||
if (cb->base.removed)
|
||||
if (script_callback_removed(&cb->base))
|
||||
return;
|
||||
|
||||
if (pressed)
|
||||
@@ -873,7 +873,7 @@ static bool button_prop_clicked(obs_properties_t *props, obs_property_t *p,
|
||||
struct python_obs_callback *cb = p_cb;
|
||||
bool ret = false;
|
||||
|
||||
if (cb->base.removed)
|
||||
if (script_callback_removed(&cb->base))
|
||||
return false;
|
||||
|
||||
lock_callback(cb);
|
||||
@@ -937,7 +937,7 @@ static bool modified_callback(void *p_cb, obs_properties_t *props,
|
||||
struct python_obs_callback *cb = p_cb;
|
||||
bool ret = false;
|
||||
|
||||
if (cb->base.removed)
|
||||
if (script_callback_removed(&cb->base))
|
||||
return false;
|
||||
|
||||
lock_callback(cb);
|
||||
@@ -1333,6 +1333,24 @@ void obs_python_script_unload(obs_script_t *s)
|
||||
if (!s->loaded || !python_loaded)
|
||||
return;
|
||||
|
||||
/* ---------------------------- */
|
||||
/* mark callbacks as removed */
|
||||
|
||||
lock_python();
|
||||
|
||||
/* XXX: scripts can potentially make callbacks when this happens, so
|
||||
* this probably still isn't ideal as we can't predict how the
|
||||
* processor or operating system is going to schedule things. a more
|
||||
* ideal method would be to reference count the script objects and
|
||||
* atomically share ownership with callbacks when they're called. */
|
||||
struct script_callback *cb = data->first_callback;
|
||||
while (cb) {
|
||||
os_atomic_set_bool(&cb->removed, true);
|
||||
cb = cb->next;
|
||||
}
|
||||
|
||||
unlock_python();
|
||||
|
||||
/* ---------------------------- */
|
||||
/* unhook tick function */
|
||||
|
||||
@@ -1350,7 +1368,7 @@ void obs_python_script_unload(obs_script_t *s)
|
||||
data->next_tick = NULL;
|
||||
}
|
||||
|
||||
lock_python();
|
||||
relock_python();
|
||||
|
||||
Py_XDECREF(data->tick);
|
||||
Py_XDECREF(data->save);
|
||||
@@ -1364,7 +1382,7 @@ void obs_python_script_unload(obs_script_t *s)
|
||||
/* ---------------------------- */
|
||||
/* remove all callbacks */
|
||||
|
||||
struct script_callback *cb = data->first_callback;
|
||||
cb = data->first_callback;
|
||||
while (cb) {
|
||||
struct script_callback *next = cb->next;
|
||||
remove_script_callback(cb);
|
||||
@@ -1532,7 +1550,7 @@ static void python_tick(void *param, float seconds)
|
||||
struct python_obs_timer *next = timer->next;
|
||||
struct python_obs_callback *cb = python_obs_timer_cb(timer);
|
||||
|
||||
if (cb->base.removed) {
|
||||
if (script_callback_removed(&cb->base)) {
|
||||
python_obs_timer_remove(timer);
|
||||
} else {
|
||||
uint64_t elapsed = ts - timer->last_ts;
|
||||
|
||||
Reference in New Issue
Block a user