Skip to content

Conversation

@ryanbreen
Copy link
Owner

@ryanbreen ryanbreen commented Dec 15, 2025

Summary

  • Fix pipe reference counts not being updated during dup(), dup2(), and FdTable::clone() operations
  • Fix UDP socket being unbound prematurely when one of multiple fds sharing the socket is closed
  • Add add_reader() and add_writer() methods to PipeBuffer for proper ref count management

Test plan

  • Build completes with zero warnings
  • Verify pipe operations work correctly after dup/fork
  • Verify UDP sockets remain bound when shared via dup until all fds are closed

🤖 Generated with Claude Code


Note

Fixes pipe reader/writer reference handling in dup/dup2/FdTable::clone and prevents premature UDP unbind by deferring to Drop when the last reference closes.

  • IPC / FDs:
    • FdTable::clone(): increment pipe reader/writer counts for cloned PipeRead/PipeWrite fds.
    • FdTable::dup2(): close existing target fd with proper pipe ref decrement; increment counts for duplicated fd.
    • FdTable::dup(): increment counts for duplicated fd; rollback increments if no slot available (EMFILE).
  • Pipes:
    • Add PipeBuffer::add_reader() and add_writer() for ref management.
  • Syscalls:
    • sys_close: stop unbinding UdpSocket on close; rely on UdpSocket::Drop when last Arc is released; adjust logging.

Written by Cursor Bugbot for commit 60d9c1f. This will update automatically on new commits. Configure here.

Two bugs fixed:

1. Pipe reference counts not updated during dup/clone operations:
   - dup(), dup2(), and FdTable::clone() were cloning the Arc<Mutex<PipeBuffer>>
     but not incrementing the readers/writers counts inside PipeBuffer
   - This caused premature EOF (writers=0) or broken pipe (readers=0) errors
     when a duplicated fd was closed
   - Added add_reader() and add_writer() methods to PipeBuffer
   - Updated dup(), dup2(), and clone() to properly maintain ref counts

2. UDP socket unbinds prematurely when fd is closed:
   - sys_close explicitly called unbind_udp() when closing a socket fd
   - With Arc<Mutex<UdpSocket>> design, multiple fds can share a socket
   - Closing one fd would unbind the socket while other fds still referenced it
   - Removed explicit unbind since UdpSocket::Drop already handles it
     when the last Arc reference is released

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ryanbreen ryanbreen merged commit c954305 into main Dec 15, 2025
2 checks passed
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on January 12

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

}

self.fds[new_fd as usize] = Some(fd_entry);
Ok(new_fd)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Race condition in dup2 when duplicating to same fd

When old_fd == new_fd, dup2 calls close_read()/close_write() and then add_reader()/add_writer() in separate lock operations. Between these calls, the pipe's reader/writer count can temporarily be zero. A concurrent write during this window will see readers == 0 and return EPIPE, even though the pipe isn't actually closed. Per POSIX, dup2(fd, fd) should return fd immediately without modifying anything. Adding an early return when old_fd == new_fd would prevent this race.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants