Your acquisition service crashes, systemd brings it straight back up, and the camera refuses every open with an in-use error. A GenICam browser shows the same picture: device there, control denied. The classic workaround, stopping and starting the transport-layer service, does free the camera, but it needs admin rights and it takes every acquisition on that host down while it runs. You rarely need it. A camera blocked after a crash follows a rule you can put numbers on: the daemon that brokers access checks whether each client's process is still alive, and it drops a dead client's lease within about one second of noticing. Get the old process truly dead, wait that second out with margin, and the camera releases itself. This guide gives the checks in order, the timing arithmetic, and the restart logic that prevents the lock next time.
What actually holds the camera
A GigE Vision camera accepts one controlling client at a time. Many SDKs put a broker between your code and that rule: a transport-layer daemon that discovers devices, hands out leases and polices them. When your process opens a camera, the daemon stores the client's process ID (PID) and polls whether that PID still exists. When the PID leaves the process table, the daemon disconnects the dead client and frees the camera. For the transport service one common Linux SDK installs, this disconnect is documented at below one second.
An ungraceful death, a segfault or a SIGKILL, breaks the assumption twice. Until the daemon's next poll, it still believes the client lives, so an early reconnect is refused. And a process that died can still be listed: a zombie has exited but its parent has not collected the exit status, so the PID stays in the table and the liveness check keeps seeing a living client. The lease then holds indefinitely. The rule did not fail; its input never went false.
That is also why the symptom is intermittent. Reap the dead process quickly and start after the one-second release, and you never see the lock. Leave a zombie behind, or start inside the window, and the open fails.
The single-client rule is the same one you hit in daytime debugging, when a second tool refuses a camera the first tool holds: GigE camera open fails in a second tool: exclusive control works that case.
Likely causes, most probable first
-
A zombie keeps the old PID alive. The crash left the process in state Z because its parent never collected the exit status, so the daemon's liveness poll still finds it. Test with
ps -o pid,stat,cmd -p <PID>: a Z in the STAT column confirms it. Fix the parent: a wrapper script must reap its children, and killing the wrapper lets init adopt and reap the orphan. Then wait out the release. - Your restart raced the release window. The service manager restarts the unit fast, well inside one second of the exit, so the new process attempts its first open while the daemon is still counting down. Failures bunched inside the first second after a crash point here. Fix: confirm the PID is gone, then wait out the margin before the first open; the worked example below sizes it.
-
A second, still-living process holds the camera. The GenICam browser you diagnosed with is still open, a second service instance runs beside the restarted one, or a recording tool never let go. Test with
pgrep -af <app>and close the extras. Fix: one owner per camera, enforced in your start script. - The daemon itself is wedged. PID gone, margin waited, camera still in use everywhere. This is the rare case, and the only one that justifies a service restart.
Worked example: timing a restart against a one-second lease
Inputs, with where each comes from:
- Release bound: 1 s. The daemon frees the camera within a second of registering that the client PID is gone; that is its documented release behavior.
- Reap time: about 0 s under systemd. The init process collects a dead unit's exit status immediately. A script parent that never reaps makes this unbounded, which is cause 1 above.
- Reconnect wait: double the release bound, the value you configure. The formula below sizes it.
The rule in words: the camera is guaranteed free only after two conditions hold. The PID is gone from the process table, and one release bound has elapsed. Add the same margin again so a slow poll cycle cannot bite.
The timeline for a segfault at t = 0:
- t = 0 s, systemd as parent: the PID leaves the process table and the release clock starts.
- t at or before 1.0 s: the daemon's poll finds no such PID, disconnects the dead client, and the camera accepts a new controller.
- t = 2.0 s: the restarted unit attempts its first open, at least 1.0 s after the guarantee.
Decision: with the full margin in place the open cannot fail on timing, because the worst-case release lands a full second before the attempt. If the camera still reports in use at reap + the margin, timing is no longer your cause; move to the live-client check, then the daemon restart. If failures only ever appear inside the first second after a crash, keep the wait at that value rather than lengthening it. Anything much past a few seconds adds dead time to every restart without buying certainty.
Clear the lock: the sequence
-
Get the old PID. If you log the PID at startup, read it from the state file; otherwise the journal entry next to the crash line, or
pgrep -f <app>, finds it. -
Confirm it is really gone.
ps -o pid,stat,cmd -p <PID>answering no-such-process is what you want. A Z in STAT means zombie: collect the exit or kill the wrapper, then re-check until the PID is gone. - Wait out the margin from the moment the PID disappeared.
- Open the camera once. Success means the lease cleared on its own; no service restart involved.
- Still in use? Look for a live second client: browser tool, duplicate instance, recorder. Close it and open again.
-
Still blocked? Restart the transport service with admin rights. For the stack that names it siGevSvc.service:
service siGevSvc stop, thenservice siGevSvc start, as its documentation prescribes.
Restarting the daemon from inside your own service is possible, by shelling out with elevated rights, and rarely right. The service would hold broad privileges, and a bug in that path can leave the daemon stopped instead of briefly offline. Give the application the least privilege it needs, keep the PID check and the margin wait in its startup path, and leave the service restart to the operator runbook.
Make the next crash release cleanly
- Release in a shutdown path. Handle the termination signal and close the device before exiting, so a managed stop frees the camera instantly. When stopping itself is what crashes, camera crash when stopping acquisition: isolate the cause separates shutdown bugs from teardown order.
- Stop the whole process group. A unit that leaves helper children running can leave one of them holding the camera; configure the unit to kill the entire group at timeout.
- Keep one owner per camera. No browser, no duplicate service, no recorder sharing the lease during production.
- Bound the restart loop. Let the service manager stop after repeated failures and raise an alarm, instead of restarting into a locked camera hundreds of times per minute; diagnose camera stream restart timeouts in vision systems handles the stream-side churn once the camera does come back.
When it is not the lease
A camera that answers nothing at all belongs to a different fault family:
- Not listed anywhere after the restart is discovery, not the lease. Linux GigE Vision camera discovery troubleshooting sorts firewall, subnet and driver causes, and Ethernet camera not discovered after reconnecting covers the address side of a device that vanished while it was down.
- Opens, then the stream dies is transport, not access. GigE Vision stream timeout: check packets, buffers and MTU is that checklist, and when several cameras drop frames together after a rough restart, troubleshooting multi-camera GigE frame drops continues from there.
- A marginal link mimics a stubborn device: renegotiated below gigabit, intermittent carrier. Swap in a known-good camera data cable before blaming software; GigE camera packet size error when your link drops below gigabit shows what a half-link does to a stream.
The decision
Old PID gone from the process table plus the worked example's margin frees the camera in the worst case, because the release bound is 1 s. Still blocked after that: find the live second client. Still blocked after that: one admin-rights restart of the transport service, in a maintenance window. If you are rebuilding the station anyway, the GigE area scan cameras finder filters by interface, resolution and shutter, and the camera configurator matches camera, cable and controller into one bill of materials; more host-side guides sit under the systems topic. Free expert support comes with every order, and contact the team when a lock survives the whole sequence.
Questions
How long does a GigE camera stay blocked after its client crashes?
About one second. The daemon frees the camera within that bound once the client PID is missing from the process table, so treat 1 s as the worst case and wait out the margin below before reconnecting. A zombie pauses the countdown: the dead process must actually leave the process table before the clock starts.
Can my C++ application release the camera programmatically at startup?
Not directly. The lease belongs to the process that died, and the daemon clears it only when that PID disappears; no client-side call revokes another process's lease. What startup code can do: record its own PID to a state file, read the previous PID back, wait while that PID still exists, then add the same margin again and open. That turns the fix into a routine the service runs on every start.
Why does the service restart cleanly sometimes and stay locked other times?
Two clocks race. The service manager restarts the unit almost immediately after the exit, while the daemon needs up to a second after the PID disappears before the camera is free. A restart that lands after the release looks like a clean recovery; one that lands inside the window fails the open and looks like a random lock. The explicit PID check plus the sized wait removes the race entirely.
When is restarting the transport service the right fix?
After the process-level checks have failed: the old PID is gone, the margin has passed, no second client holds the device, and the camera still reports in use. Then stop and start the transport daemon with admin rights; for the Linux stack that names it siGevSvc.service, that means service siGevSvc stop followed by service siGevSvc start. Do it in a maintenance window, because every camera the daemon brokers on that host is offline while it is down.
Does a USB3 Vision camera get stuck the same way after a crash?
Rarely. USB3 Vision has no network lease: the kernel closes a dead process's device handles, so a fresh open usually succeeds straight away. The post-crash failures differ: a device node left locked by a second user, or an interface still claimed. If a USB camera refuses to reopen, unplug it, let the host re-enumerate it, and check for another process holding the device before you look for a lease.