Drop a claim when its client leaves the bus
A claim is held by a bus connection. If that connection goes away -- the client crashed, was killed, or never called Release -- the claim has to go with it, or the device is AlreadyInUse for everyone until the daemon restarts. fprintd watches the claimant's name for exactly this reason. Found the hard way: a Claim issued from one busctl invocation, which exits the moment it returns, left the device permanently claimed by a connection that no longer existed. The daemon now subscribes to NameOwnerChanged for the claimant's unique name and, when it loses its owner, cancels any running operation and clears the claim. Release goes through the same path so the subscription is torn down either way. Verified with the stock client killed mid-verify under timeout: the claim dropped, the verify cancelled, and fprintd-list worked immediately after.
This commit is contained in:
parent
9fbf5e6c73
commit
32fe0ac665
1 changed files with 35 additions and 3 deletions
|
|
@ -1589,6 +1589,38 @@ struct Claim {
|
|||
};
|
||||
Claim g_claim;
|
||||
GDBusMethodInvocation* g_pendingClaim = nullptr;
|
||||
guint g_claimWatch = 0;
|
||||
|
||||
void DropClaim(const char* why) {
|
||||
if (g_claimWatch) {
|
||||
g_dbus_connection_signal_unsubscribe(g_conn, g_claimWatch);
|
||||
g_claimWatch = 0;
|
||||
}
|
||||
if (g_claim.op != Op::None && g_worker) g_worker->CancelOp();
|
||||
if (g_claim.held)
|
||||
std::println("claim by {} for {} dropped: {}", g_claim.sender, g_claim.user, why);
|
||||
g_claim = {};
|
||||
}
|
||||
|
||||
// A claim is held by a bus connection. If that connection goes away -- the
|
||||
// client crashed, was killed, or simply never called Release -- the claim
|
||||
// must go with it, or the device is wedged for everyone until the daemon
|
||||
// restarts. fprintd watches the claimant's name for exactly this reason. Seen
|
||||
// the hard way: a Claim from one busctl invocation, which exits immediately,
|
||||
// left the device permanently "AlreadyInUse".
|
||||
void WatchClaimant(const std::string& sender) {
|
||||
g_claimWatch = g_dbus_connection_signal_subscribe(
|
||||
g_conn, "org.freedesktop.DBus", "org.freedesktop.DBus", "NameOwnerChanged",
|
||||
"/org/freedesktop/DBus", sender.c_str(), G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
[](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*,
|
||||
GVariant* params, gpointer) {
|
||||
const gchar* name = nullptr; const gchar* oldOwner = nullptr; const gchar* newOwner = nullptr;
|
||||
g_variant_get(params, "(&s&s&s)", &name, &oldOwner, &newOwner);
|
||||
if (g_claim.held && name && g_claim.sender == name && newOwner && *newOwner == '\0')
|
||||
DropClaim("client left the bus");
|
||||
},
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
std::string MapPath(std::uint32_t uid) {
|
||||
return fingerprintd::store::PathForUid(g_stateDir, uid);
|
||||
|
|
@ -1685,7 +1717,7 @@ void PostEvent(std::unique_ptr<Event> ev) {
|
|||
g_claim.sender, g_claim.user, g_claim.uid, ev->templates);
|
||||
g_dbus_method_invocation_return_value(ev->invocation, nullptr);
|
||||
} else {
|
||||
g_claim = {};
|
||||
DropClaim("group selection failed");
|
||||
ReturnError(ev->invocation, "Internal", "could not select the user's group");
|
||||
}
|
||||
g_pendingClaim = nullptr;
|
||||
|
|
@ -1763,6 +1795,7 @@ void HandleDevice(GDBusMethodInvocation* inv, std::string_view method, GVariant*
|
|||
g_claim.uid = who->second;
|
||||
g_claim.fingers = LoadMap(g_claim.uid);
|
||||
g_pendingClaim = inv;
|
||||
WatchClaimant(g_claim.sender);
|
||||
g_worker->Post(Job{ .kind = Job::Kind::Claim, .uid = g_claim.uid, .invocation = inv });
|
||||
return;
|
||||
}
|
||||
|
|
@ -1771,8 +1804,7 @@ void HandleDevice(GDBusMethodInvocation* inv, std::string_view method, GVariant*
|
|||
ReturnError(inv, "ClaimDevice", "device is not claimed by you");
|
||||
return;
|
||||
}
|
||||
if (g_claim.op != Op::None) g_worker->CancelOp();
|
||||
g_claim = {};
|
||||
DropClaim("released");
|
||||
g_dbus_method_invocation_return_value(inv, nullptr);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue