4

I wrote a macOS Mojave LaunchDaemon which triggers a shell script to run the imagesnap program. The purpose is to capture a still image from the camera every second.

The Problem: the daemon fails with the error below. I can't figure out what is causing it to fail but it seems like maybe the camera is not availble or root/launchd does not have camera permission. Note that the script, automator app, and running imagesnap on the command line all work by themselves and only fail once I try to run them from the LaunchDaemon.

What I figured out:

  1. The script runs fine as a normal user, as a normal user using sudo, and as the root user logged in using sudo su. I ran it in iTerm2 and got a popup requesting camera access, which I approved. The script fails when run by the LaunchDaemon.
  2. I created an Automator .app and ran that using /usr/bin/open. Again I got a popup requesting camera permission which I approved. The automator .app fails when run by the LaunchDaemon.
  3. The LaunchDaemon runs the script without error if I omit the imagesnap command in line 4.
  4. The .plist is loaded and started and executes the shell script continuously as it should with the KeepAlive key set.

snapscript_err.log snippet

2019-02-20 15:54:06.183 imagesnap[34024:2892654] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVCaptureStillImageOutput captureStillImageAsynchronouslyFromConnection:completionHandler:] Inactive/invalid connection passed'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff33eb0ded __exceptionPreprocess + 256
    1   libobjc.A.dylib                     0x00007fff5ff7c720 objc_exception_throw + 48
    2   AVFoundation                        0x00007fff2fe56373 -[AVCaptureStillImageOutput _receiveSampleBuffer:] + 0
    3   imagesnap                           0x000000010590dfcf imagesnap + 12239
    4   imagesnap                           0x000000010590d618 imagesnap + 9752
    5   imagesnap                           0x000000010590cbab imagesnap + 7083
    6   imagesnap                           0x000000010590c6ca imagesnap + 5834
    7   libdyld.dylib                       0x00007fff6104aed9 start + 1
    8   ???                                 0x0000000000000003 0x0 + 3
)
libc++abi.dylib: terminating with uncaught exception of type NSException
/usr/local/bin/snapscript.sh: line 4: 34024 Abort trap: 6           /usr/local/bin/imagesnap -t 1

system.log snippet

Feb 20 15:57:58 macbook com.apple.xpc.launchd[1] (com.example.snapscript[34116]): Service exited with abnormal code: 134
Feb 20 15:57:58 macbook com.apple.xpc.launchd[1] (com.example.snapscript): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
Feb 20 15:58:09 macbook com.apple.xpc.launchd[1] (com.example.snapscript[34121]): Service exited with abnormal code: 134
Feb 20 15:58:09 macbook com.apple.xpc.launchd[1] (com.example.snapscript): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
Feb 20 15:58:19 macbook com.apple.xpc.launchd[1] (com.example.snapscript[34126]): Service exited with abnormal code: 134
Feb 20 15:58:19 macbook com.apple.xpc.launchd[1] (com.example.snapscript): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.

/Library/LaunchDaemon/com.example.snapscript.plist file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>RunAtLoad</key>
  <true/>

    <key>Label</key>
    <string>com.example.snapscript</string>

    <key>ProgramArguments</key>
  <array>
    <string>/usr/local/bin/snapscript.sh</string>
  </array>

  <key>KeepAlive</key>
  <true/>

    <key>StandardOutPath</key>
    <string>/var/log/snapscript/snapscript.log</string>

    <key>StandardErrorPath</key>
    <string>/var/log/snapscript/snapscript_err.log</string>
</dict>
</plist>

/usr/local/bin/snapscript.sh file

#!/bin/bash

cd /var/snapscript
/usr/local/bin/imagesnap -t 1
dangerginger
  • 135
  • 7
  • 1
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(avCaptureRuntimeError:) name:AVCaptureSessionRuntimeErrorNotification object:nil]; also check [captureDevice isConnected] && [captureDevice isInUseByAnotherApplication] and also check if you have a valid output [_captureSession outputs] – Marek H Feb 20 '19 at 08:13
  • 1
    Did you try calling [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]? What's the returned status? – Elist Apr 05 '19 at 08:43
  • 1
    I have same issue, After debugging I found that app is not requesting to camera permission, even though I have added 'Privacy - Camera Usage Description' in info.plist. Did you find any solution? – Saqib Omer May 02 '19 at 15:53
  • @SaqibOmer I haven't found a solution to this either. – dangerginger May 04 '19 at 22:31
  • @Elist To be clear I am not writing the AVCapture portion of the code myself. I'm calling the imagesnap binary. I may have to change my approach. – dangerginger May 04 '19 at 22:33
  • I found solution. 1: You have to launch application manually for the first time. If there are more than one target, all targets should contain ''Privacy - Camera Usage Description' in info.plist – Saqib Omer May 06 '19 at 06:57
  • @SaqibOmer This doesn't work for me. In my case I'm trying to use ffmpeg - Terminal popped up and asked for permission, and it even runs under tmux, but it still fails when run as a launch daemon. – Michael Mar 16 '20 at 18:47

0 Answers0