Skip to content

fix(tty): implement TIOCGPTPEER and correct devpts slave lifecycle#1982

Merged
fslongjin merged 7 commits into
DragonOS-Community:masterfrom
fslongjin:fix/pty-tiocgptpeer
Jun 22, 2026
Merged

fix(tty): implement TIOCGPTPEER and correct devpts slave lifecycle#1982
fslongjin merged 7 commits into
DragonOS-Community:masterfrom
fslongjin:fix/pty-tiocgptpeer

Conversation

@fslongjin

@fslongjin fslongjin commented Jun 21, 2026

Copy link
Copy Markdown
Member

Summary

  • Implement TIOCGPTPEER so a PTY master fd can open its slave peer through the cached slave inode on the master, instead of resolving /dev/pts/N again after the devpts entry may have been unlinked.
  • Fix the devpts slave lifetime model by tracking active slave file descriptions with a reference count and decrementing it on file close, preventing premature index reuse when multiple TIOCGPTPEER slave fds exist.
  • Fix O_PATH open file description semantics in VFS: O_PATH no longer triggers inode open/flush/close paths and no longer replaces FIFO path fds with the internal pipe inode.
  • Ensure TIOCGPTPEER(O_PATH | ...) creates only a path fd, does not become a real PTY slave open, and does not keep the devpts index reserved after master close.
  • Add reserved fd slot support to the fd table so ioctls can install newly created fds atomically; update fcntl dup handling accordingly.
  • Harden PTY backlog draining for large writes by using a fixed-size PTY ring buffer, lossless drain/wakeup semantics, and condition-based EPOLLOUT waiting to avoid lost wakeups.
  • Preserve n_tty OPOST partial-output state across short driver writes, while handling TCIFLUSH/TCOFLUSH/TCIOFLUSH with Linux-compatible input/output responsibilities.
  • Add dunitest coverage for locked/unlocked TIOCGPTPEER, unlinked devpts access, multiple slave fd index retention/reuse, O_PATH peer behavior, FIFO O_PATH identity, PTY hangup behavior, large PTY backlog draining, canonical reads, and OPOST/flush edge cases.

Test plan

  • make fmt
  • make fmt -C kernel
  • make kernel
  • make -C user/apps/tests/dunitest build-suites
  • make -C user/apps/tests/dunitest bin/normal/tty_pty_hangup_test
  • Host Linux: user/apps/tests/dunitest/bin/normal/tty_pty_hangup_test --gtest_filter='TtyPtyHangup.TiocgptpeerOPath*:TtyPtyHangup.OPathFifoKeepsPathInodeAndDoesNotBlock:TtyPtyHangup.MultipleTiocgptpeerSlaveFdsKeepIndexReserved'
  • Host Linux: user/apps/tests/dunitest/bin/normal/tty_pty_hangup_test --gtest_filter='TtyPtyHangup.LargeOpostSlaveWriteDrainsAndPreservesOnlcr:TtyPtyHangup.LargeRawSlaveWriteDrainsWithSmallMasterReads:TtyPtyHangup.LargeCanonicalMasterWriteDrainsWithSmallSlaveReads:TtyPtyHangup.TciflushDoesNotDiscardLargeOpostSlaveOutput'
  • DragonOS QEMU guest: /opt/tests/dunitest/bin/normal/tty_pty_hangup_test, 28/28 passed
  • Serial log check: no failed to close file / slave file close without active open

Note: make test-dunit previously failed before entering QEMU while writing the disk image, with an existing cp: cannot stat ... Bad message issue for gVisor test files. The kernel and updated dunitest binary were then validated in a DragonOS QEMU guest with make qemu-nographic.

Made with Cursor

TIOCGPTPEER must open the peer inode cached on the master rather than
re-resolving /dev/pts/N after unlink. Track multiple slave fds with a
counter and add fd-table reservation so ioctl can install the new fd
atomically. Add dunitest coverage for lock, unlink, and index reuse.

Signed-off-by: longjin <longjin@dragonos.org>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added the Bug fix A bug is fixed in this pull request label Jun 21, 2026
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d74674ca1d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kernel/src/driver/tty/tty_device.rs
Signed-off-by: longjin <longjin@dragonos.org>
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 77ce34edc7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kernel/src/driver/tty/pty/unix98pty.rs Outdated
Comment thread kernel/src/driver/tty/tty_ldisc/ntty.rs Outdated
Signed-off-by: longjin <longjin@dragonos.org>
Signed-off-by: longjin <longjin@dragonos.org>
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcbaf1ca81

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kernel/src/driver/tty/pty/unix98pty.rs
Signed-off-by: longjin <longjin@dragonos.org>
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95478ac711

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kernel/src/driver/tty/tty_device.rs
Comment thread kernel/src/driver/tty/tty_ldisc/ntty.rs Outdated
Signed-off-by: longjin <longjin@dragonos.org>
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 45be36149f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread kernel/src/driver/tty/tty_ldisc/ntty.rs Outdated
Signed-off-by: longjin <longjin@dragonos.org>
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd9551cf67

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +468 to +470
let drain_len = done.min(self.outbuf.len());
if drain_len != 0 {
self.outbuf.drain(0..drain_len);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 按提交长度释放 virtio-console TX 缓冲

在 virtio-console 的发送队列完成时,complete_tx() 返回的是 used ring 的 len,而 TX 描述符只有 device-readable buffer,常见设备会把这个长度报告为 0;这里用 donedrain 会导致已经发送的字节一直留在 outbuf 中。结果是在 /dev/hvc0 有输出完成中断后,同一前缀会被反复重新提交,write_room() 也会逐步被已发送数据占满,最终阻塞/返回 EAGAIN;应按当初提交的 tx_len 清理缓冲,而不是按 used len。

Useful? React with 👍 / 👎.

@fslongjin fslongjin Jun 22, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I re-checked the current branch, and this issue does not appear to exist in the current implementation.

complete_tx() uses pop_used() only to confirm and reclaim the matching TX descriptor. The current code does not propagate the virtqueue used-ring len to the upper layer. Instead, it saves the originally submitted tx_len, calls pop_used(token, &[tx_buf], &mut [])?, clears the pending TX state, and returns Ok(Some(tx_len)). Therefore, the done value used by flush_output_locked() for outbuf.drain(0..drain_len) is the originally submitted length, not the device-reported used length.

This also matches the Linux virtio-console model: on TX completion, virtqueue_get_buf(out_vq, &len) is used to reclaim the submitted buffer, while output progress is tied to the submitted buffer lifecycle rather than treating the used length as the number of transmitted bytes. So even if a device reports 0 for a device-readable TX buffer, the current DragonOS code will not repeatedly resubmit the same prefix or fill write_room() for that reason.

@fslongjin fslongjin merged commit df72741 into DragonOS-Community:master Jun 22, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug fix A bug is fixed in this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant