-
Notifications
You must be signed in to change notification settings - Fork 3
fix: make dcell fully @safe for consumers (fixes #10) #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Caution Review failedThe pull request is closed. WalkthroughTightens and standardizes safety and exception guarantees by adding Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (12)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
source/dcell/ttyscreen.d (1)
559-583: Addnothrowattribute toTtyEventQ.put()override.The base class
EventQ.putis declared as@safe nothrow(source/dcell/event.d:82), but the override inTtyEventQat line 559 only specifies@safe, omittingnothrow. The derived class must preserve or strengthen the base class contract. Addnothrowto match:override void put(Event ev) @safe nothrow { super.put(ev); ti.wakeUp(); }source/dcell/termio.d (1)
388-407: Use atomic store forsigFdassignment or implement CAS-based initialization.The
watchResizefunction has a genuine TOCTOU race condition on lines 393-402. TheatomicLoad(sigFd) == -1check is followed by non-atomic assignments tosigPipe,sigWfd,sigRfd, andsigFd. If multiple threads callwatchResizeconcurrently, both could pass the check and overwrite globals, with the signal handler inhandleSigWinCh(line 359) writing to a partially-initialized or stalesigWfd.Replace the plain assignment
sigFd = fd;(line 402) withatomicStore(&sigFd, fd);and usecas(compare-and-swap) for the initial check-and-set sequence. Also fix the plain assignment at line 416 inignoreResize.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
demos/colors/source/colors.d(4 hunks)demos/hello/dub.json(1 hunks)demos/mouse/dub.json(1 hunks)source/dcell/common.d(1 hunks)source/dcell/cursor.d(1 hunks)source/dcell/event.d(1 hunks)source/dcell/parser.d(12 hunks)source/dcell/screen.d(12 hunks)source/dcell/termio.d(12 hunks)source/dcell/tty.d(2 hunks)source/dcell/ttyscreen.d(20 hunks)source/dcell/wintty.d(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- demos/colors/source/colors.d
- demos/hello/dub.json
- source/dcell/cursor.d
- demos/mouse/dub.json
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-14T19:58:59.815Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 53
File: source/dcell/ttyscreen.d:557-577
Timestamp: 2025-12-14T19:58:59.815Z
Learning: In source/dcell/ttyscreen.d, the TtyEventQ class intentionally has different behavior between put() and opOpAssign methods. The put() method calls ti.wakeUp() for external callers injecting synthetic events, while opOpAssign (used via ~= operator) bypasses wakeUp() as a performance optimization when appending events internally during tty event processing where the thread is already active.
Applied to files:
source/dcell/event.dsource/dcell/tty.dsource/dcell/ttyscreen.d
📚 Learning: 2025-12-14T19:56:40.073Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 53
File: source/dcell/screen.d:96-126
Timestamp: 2025-12-14T19:56:40.073Z
Learning: In dcell, the EventQ class is intentionally designed as both an input range and an output range of Event. The output range functionality allows applications to inject synthetic events into the event stream.
Applied to files:
source/dcell/event.d
📚 Learning: 2025-12-08T19:10:45.993Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:763-766
Timestamp: 2025-12-08T19:10:45.993Z
Learning: In source/dcell/ttyscreen.d, the newTtyScreen() factory function intentionally does not accept a term parameter because the TtyScreen constructor handles environment variable resolution internally with an optional term parameter. Users needing to override the terminal type should call the constructor directly: new TtyScreen(newDevTty(), "custom-term").
Applied to files:
source/dcell/ttyscreen.dsource/dcell/wintty.d
🔇 Additional comments (17)
source/dcell/common.d (1)
4-4: LGTM!Copyright year update is appropriate for the 2025 modifications.
source/dcell/event.d (1)
82-85: LGTM!The
@safe nothrowannotations are appropriate for the array append operation. This strengthens the safety contract for consumers of the EventQ output range interface.source/dcell/screen.d (1)
25-265: LGTM!The comprehensive
@safeannotations across theScreeninterface establish a strong safety contract for consumers. Thefinalmethod implementations correctly delegate to other@safemethods, maintaining consistency throughout the interface.source/dcell/parser.d (3)
313-318: LGTM!The
pure @safe @nogcannotations are correct. The method performs only safe operations: saving a reference, nulling the field, and returning the slice.
386-660: Appropriate use of@trusted.The
scan()method correctly uses@trustedas it encapsulates low-level byte manipulation and UTF decoding operations that cannot be verified as@safeby the compiler, but are manually verified to be memory-safe.
1094-1218: LGTM!The event factory methods (
newFocusEvent,newKeyEvent,newMouseEvent,newPasteEvent) correctly usenothrow @safeas they only perform struct initialization and callMonoTime.currTime()which has matching attributes.source/dcell/tty.d (1)
24-95: LGTM!The
Ttyinterface appropriately uses@trustedfor I/O methods that interact with system calls, whileresized()correctly uses@safesince it's a simple flag check. This establishes clear safety contracts that implementations must satisfy.source/dcell/wintty.d (3)
64-69: @trusted annotation is appropriate for Windows API calls.The constructor correctly uses
@trustedsince it calls Windows kernel APIs (GetStdHandle,CreateEventW) that are declared asextern(Windows) @nogc nothrowbut cannot be verified by the compiler for memory safety.
112-114: LGTM: Empty method is correctly marked @safe.The
flush()method has an empty body and correctly uses@safe.
201-206: LGTM: Pure data access correctly marked @safe.The
resized()method only reads and writes member variables without any unsafe operations, making@safethe correct annotation.source/dcell/termio.d (3)
59-62: LGTM: Constructor correctly annotated.Simple assignment of a string parameter to a member variable is correctly marked
nothrow @safe.
113-118: @trusted is appropriate here, but note the mixed safety levels.The
save()method is marked@trustedwhich is correct since it callsisatty()andtcgetattr()(C library functions). However, it also throws exceptions viathrowandenforce, which is fine since it's not markednothrow.
314-318: Verify thatwasResized(fd)maintains@nogccontract.The
resized()method is markednothrow @safe @nogc, and it callswasResized(fd). Ensure thatwasResized(line 421) also maintains the@nogccontract, which it does (nothrow @trusted @nogc).source/dcell/ttyscreen.d (4)
316-327: LGTM: Pure cell buffer operations correctly marked @safe.The
clear()method performs safe operations on the cell buffer. The @safe annotation is appropriate.
383-386: LGTM: Accessor correctly marked with full safety guarantees.The
colors()getter is appropriately markedconst pure nothrow @safesince it only returns a struct field value.
605-616: LGTM: Internal I/O helpers correctly marked @safe.The
puts()andflush()methods useOutBufferoperations which are @safe. Theflush()method callsti.write()andti.flush()which should be @safe or @trusted (verified in termio.d and wintty.d).
449-502: No action needed - @safe compatibility is correctly maintained.All methods called by
waitForEventare properly marked:
parser.events()is@safeparser.parse()is@safeti.resized()is@safeti.read()is@trustedA
@safefunction can correctly call@trustedfunctions. Theread()method is appropriately marked@trustedbecause it performs OS-level system calls that require unsafe operations; this is the intended design for FFI and platform-specific code.
While here, the copyrights for files updates this year are updated for 2025.
While here, the copyrights for files updates this year are updated for 2025.
Summary by CodeRabbit
Refactor
Bug Fixes
Chores
✏️ Tip: You can customize this high-level summary in your review settings.