commit:     f1d2a62cf085871c53d89cb75e0e74c016e74c16
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Tue Nov 18 09:14:20 2025 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Tue Nov 18 09:14:20 2025 +0000
URL:        https://gitweb.gentoo.org/proj/steve.git/commit/?id=f1d2a62c

Initial support for token reclaiming

Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 steve.cxx | 51 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/steve.cxx b/steve.cxx
index 0ff6bb0..81e88f4 100644
--- a/steve.cxx
+++ b/steve.cxx
@@ -13,6 +13,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cerrno>
+#include <csignal>
 #include <deque>
 #include <unordered_map>
 
@@ -89,6 +90,37 @@ static int steve_process_arg(
        return 0;
 }
 
+static void steve_wake_waiters(steve_state *state)
+{
+       while (state->tokens > 0 && !state->read_waiters.empty()) {
+               const steve_read_waiter *read_waiter = 
&state->read_waiters.front();
+
+               state->tokens--;
+               state->processes[read_waiter->pid].tokens_held++;
+               if (state->verbose)
+                       printf("Giving job token to PID %ld, %d left, %d tokens 
held by process\n",
+                                       read_waiter->pid, state->tokens, 
state->processes[read_waiter->pid].tokens_held);
+               fuse_reply_buf(read_waiter->req, "+", 1);
+               state->read_waiters.pop_front();
+       }
+}
+
+static void steve_check_processes(steve_state *state)
+{
+       for (auto it = state->processes.begin(); it != state->processes.end();)
+       {
+               if (kill(it->first, 0) == -1 && errno == ESRCH) {
+                       state->tokens += it->second.tokens_held;
+                       fprintf(stderr, "Process %ld disappeared while holding 
%d tokens, "
+                                       "%d tokens available after returning 
them\n",
+                                       it->first, it->second.tokens_held, 
state->tokens);
+                       it = state->processes.erase(it);
+                       steve_wake_waiters(state);
+               } else
+                       ++it;
+       }
+}
+
 static void steve_init(void *userdata, struct fuse_conn_info *conn)
 {
        steve_state *state = static_cast<steve_state *>(userdata);
@@ -157,6 +189,10 @@ static void steve_read(
                return;
        }
 
+       /* check if we have tokens to reclaim */
+       if (state->tokens == 0)
+               steve_check_processes(state);
+
        /* no need to support reading more than one token at a time */
        if (state->tokens > 0) {
                state->tokens--;
@@ -180,21 +216,6 @@ static void steve_read(
        fuse_req_interrupt_func(req, steve_interrupt, state);
 }
 
-static void steve_wake_waiters(steve_state *state)
-{
-       while (state->tokens > 0 && !state->read_waiters.empty()) {
-               const steve_read_waiter *read_waiter = 
&state->read_waiters.front();
-
-               state->tokens--;
-               state->processes[read_waiter->pid].tokens_held++;
-               if (state->verbose)
-                       printf("Giving job token to PID %ld, %d left, %d tokens 
held by process\n",
-                                       read_waiter->pid, state->tokens, 
state->processes[read_waiter->pid].tokens_held);
-               fuse_reply_buf(read_waiter->req, "+", 1);
-               state->read_waiters.pop_front();
-       }
-}
-
 static void steve_write(
        fuse_req_t req, const char *buf, size_t size, off_t off,
        struct fuse_file_info *fi)

Reply via email to