48 void *compositionBinaryHandle)
57 hasBeenUnpaused =
false;
59 wasStopCompositionCalled =
false;
64 terminationDisabledCount = 0;
65 terminationDisabledQueue = dispatch_queue_create(
"org.vuo.runtime.terminationDisabled", NULL);
67 stopQueue = dispatch_queue_create(
"org.vuo.runtime.stop", NULL);
69 waitForStopTimer = NULL;
70 waitForStopCanceledSemaphore = NULL;
74 vuoInstanceInit = NULL;
75 vuoInstanceFini = NULL;
76 vuoInstanceTriggerStart = NULL;
77 vuoInstanceTriggerStop = NULL;
94 dispatch_source_cancel(waitForStopTimer);
95 dispatch_semaphore_wait(waitForStopCanceledSemaphore, DISPATCH_TIME_FOREVER);
96 dispatch_release(waitForStopTimer);
97 dispatch_release(waitForStopCanceledSemaphore);
102 dispatch_release(stopQueue);
112 ostringstream errorMessage;
114 vuoSetup = (vuoSetupType) dlsym(compositionBinaryHandle,
"vuoSetup");
117 errorMessage <<
"The composition couldn't be started because its vuoSetup() function couldn't be found : " << dlerror();
121 vuoCleanup = (vuoCleanupType) dlsym(compositionBinaryHandle,
"vuoCleanup");
124 errorMessage <<
"The composition couldn't be started because its vuoCleanup() function couldn't be found : " << dlerror();
128 vuoInstanceInit = (vuoInstanceInitType) dlsym(compositionBinaryHandle,
"vuoInstanceInit");
129 if (! vuoInstanceInit)
131 errorMessage <<
"The composition couldn't be started because its vuoInstanceInit() function couldn't be found : " << dlerror();
135 vuoInstanceFini = (vuoInstanceFiniType) dlsym(compositionBinaryHandle,
"vuoInstanceFini");
136 if (! vuoInstanceFini)
138 errorMessage <<
"The composition couldn't be started because its vuoInstanceFini() function couldn't be found : " << dlerror();
142 vuoInstanceTriggerStart = (vuoInstanceTriggerStartType) dlsym(compositionBinaryHandle,
"vuoInstanceTriggerStart");
143 if (! vuoInstanceTriggerStart)
145 errorMessage <<
"The composition couldn't be started because its vuoInstanceTriggerStart() function couldn't be found : " << dlerror();
149 vuoInstanceTriggerStop = (vuoInstanceTriggerStopType) dlsym(compositionBinaryHandle,
"vuoInstanceTriggerStop");
150 if (! vuoInstanceTriggerStop)
152 errorMessage <<
"The composition couldn't be started because its vuoInstanceTriggerStop() function couldn't be found : " << dlerror();
187 bool VuoRuntimeState::mayBeTerminated(
void)
190 dispatch_sync(terminationDisabledQueue, ^{
191 ret = (terminationDisabledCount == 0);
205 dispatch_sync(terminationDisabledQueue, ^{
206 ++terminationDisabledCount;
215 dispatch_sync(terminationDisabledQueue, ^{
216 --terminationDisabledCount;
217 if (terminationDisabledCount < 0)
218 terminationDisabledCount = 0;
238 hasBeenUnpaused =
true;
239 __block
bool initDone =
false;
240 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
242 vuoInstanceTriggerStart();
253 if (! continueIfRunnerDies)
263 vuoInstanceTriggerStop();
273 if (! hasBeenUnpaused)
275 hasBeenUnpaused =
true;
278 vuoInstanceTriggerStart();
287 if (! isBeingReplaced)
292 stopComposition(isBeingReplaced, timeoutInSeconds);
294 if (timeoutInSeconds >= 0)
297 dispatch_sync(dispatch_get_main_queue(), ^{
306 if (isLastEverInProcess)
308 typedef void (*VuoImageTextCacheFiniType)(void);
309 VuoImageTextCacheFiniType vuoImageTextCacheFini = (VuoImageTextCacheFiniType) dlsym(RTLD_DEFAULT,
"VuoImageTextCache_fini");
310 if (vuoImageTextCacheFini)
311 vuoImageTextCacheFini();
332 if (persistentState->communicator->hasZmqConnection())
334 persistentState->communicator->sendStopRequested();
337 waitForStopTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, persistentState->communicator->getControlQueue());
338 dispatch_source_set_timer(waitForStopTimer, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 2.), NSEC_PER_SEC * 2, NSEC_PER_SEC/10);
339 waitForStopCanceledSemaphore = dispatch_semaphore_create(0);
341 dispatch_source_set_event_handler(waitForStopTimer, ^{
342 stopComposition(false, 5);
343 dispatch_source_cancel(waitForStopTimer);
346 dispatch_source_set_cancel_handler(waitForStopTimer, ^{
347 dispatch_semaphore_signal(waitForStopCanceledSemaphore);
350 dispatch_resume(waitForStopTimer);
354 stopComposition(false, 5);
358 persistentState->communicator->interruptListeningForControl();
370 void VuoRuntimeState::stopComposition(
bool isBeingReplaced,
int timeoutInSeconds)
372 dispatch_retain(stopQueue);
374 dispatch_sync(stopQueue, ^{
378 if (wasStopCompositionCalled)
380 wasStopCompositionCalled =
true;
382 killProcessAfterTimeout(timeoutInSeconds);
384 dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
390 vuoInstanceTriggerStop();
397 if (!isBeingReplaced)
410 dispatch_release(stopQueue);
427 void VuoRuntimeState::killProcessAfterTimeout(
int timeoutInSeconds)
429 if (timeoutInSeconds < 0)
432 if (runnerPid == getpid())
437 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeoutInSeconds * NSEC_PER_SEC),
438 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
442 dispatch_source_t backupTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
443 dispatch_source_set_timer(backupTimer, dispatch_time(DISPATCH_TIME_NOW, timeoutInSeconds * NSEC_PER_SEC), timeoutInSeconds * NSEC_PER_SEC, NSEC_PER_SEC/10);
444 dispatch_source_set_event_handler(backupTimer, ^{
446 VUserLog(
"Warning: Waited %d seconds for the composition to cleanly shut down, but it's still running. Now I'm force-quitting it.", timeoutInSeconds * 2);
447 kill(getpid(), SIGKILL);
449 dispatch_resume(backupTimer);
451 __block
bool eventLoopMayBeTerminated;
452 dispatch_sync(dispatch_get_main_queue(), ^{
455 if (mayBeTerminated() && eventLoopMayBeTerminated)
458 VUserLog(
"Warning: Waited %d seconds for the composition to cleanly shut down, but it's still running. Now I'm force-quitting it.", timeoutInSeconds);
459 kill(getpid(), SIGKILL);
462 dispatch_source_cancel(backupTimer);
463 dispatch_release(backupTimer);