commit:     47fdc92256b2437431ceb5fbbdc1a1e75635357c
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Thu Nov 27 19:54:01 2025 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Thu Nov 27 19:54:01 2025 +0000
URL:        https://gitweb.gentoo.org/proj/steve.git/commit/?id=47fdc922

Add a hack for `nasm-rs` pre-releasing tokens

`nasm-rs` is releasing a token that it did not acquire itself in order
to account for the extra token acquired for the parent process (make's
"implicit slot").  While this is invalid, let's add a workaround to
permit the process to hold -1 tokens in order to unbreak builds while
packages go through Cargo's insanely broken update model.

Bug: https://github.com/medek/nasm-rs/issues/44
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 steve.cxx | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/steve.cxx b/steve.cxx
index 8b61368..a6ed034 100644
--- a/steve.cxx
+++ b/steve.cxx
@@ -56,7 +56,7 @@ struct steve_poll_waiter {
 
 struct steve_process {
        int pid_fd{-1};
-       size_t tokens_held{0};
+       ssize_t tokens_held{0};
        std::unique_ptr<struct event, std::function<void(struct event*)>> event;
 
        ~steve_process() {
@@ -283,11 +283,24 @@ static void steve_write(
                fuse_reply_err(req, EIO);
                return;
        }
+       if (size > SSIZE_MAX) {
+               std::print(stderr, "Warning: process {} tried to return more 
than SSIZE_MAX tokens\n",
+                               fi->fh);
+               fuse_reply_err(req, EFBIG);
+               return;
+       }
 
-       if (state->processes[fi->fh].tokens_held < size) {
+       /* workaround for https://github.com/medek/nasm-rs/issues/44 */
+       if (state->processes[fi->fh].tokens_held == 0 && size == 1) {
+               std::print(stderr, "Warning: process {} pre-released an 
unacquired token, please report a bug upstream\n",
+                               fi->fh);
+       } else if (state->processes[fi->fh].tokens_held < 
static_cast<ssize_t>(size)) {
                std::print(stderr, "Warning: process {} tried to return {} 
tokens while holding only {} tokens, capping\n",
                                fi->fh, size, 
state->processes[fi->fh].tokens_held);
-               size = state->processes[fi->fh].tokens_held;
+               if (state->processes[fi->fh].tokens_held < 0)
+                       size = 0;
+               else
+                       size = state->processes[fi->fh].tokens_held;
        }
        if (size == 0) {
                fuse_reply_err(req, ENOSPC);

Reply via email to