- README.md - User-facing documentation
- Module docs -
//!comments at module top - Function docs -
///comments on public items - Code comments -
/* */and//inline comments - SAFETY comments - Required for unsafe blocks
- Clear purpose statement - "GNU timeout clone for macOS"
- Installation instructions - Homebrew formula provided
- Usage examples - Multiple practical examples
- Feature comparison - vs GNU timeout
- Technical details - Wall clock vs CPU time diagram
- Exit code documentation - Matches GNU spec
# timeout - GNU timeout for macOS
├── Why this exists
├── Features
├── Installation
├── Usage
│ ├── Basic timeout
│ ├── Send different signal
│ ├── Escalate to SIGKILL
│ ├── Verbose mode
│ ├── JSON output
│ └── Environment variables
├── Exit Status
├── Options Reference
├── How It Works (diagram)
└── LicenseUser documentation is comprehensive and well-organized.
| Module | Has //! |
Has /* */ header |
Quality |
|---|---|---|---|
| lib.rs | No | No | Minimal |
| main.rs | No | Yes | Not in rustdoc |
| args.rs | No | No | None |
| duration.rs | No | Yes | Not in rustdoc |
| error.rs | No | Yes | Not in rustdoc |
| signal.rs | No | No | None |
| process.rs | No | Yes | Not in rustdoc |
| runner.rs | No | Yes | Not in rustdoc |
| wait.rs | No | Yes | Not in rustdoc |
| sync.rs | No | Yes | Not in rustdoc |
| allocator.rs | No | Yes | Not in rustdoc |
| io.rs | No | Yes | Not in rustdoc |
| panic.rs | No | Yes | Not in rustdoc |
Key Issue: Most modules have informative /* ... */ block comments at the top, but these are not doc comments. They don't appear in cargo doc output.
Current (code comment - not in rustdoc):
/*
* duration.rs
*
* Parse "30s", "100ms", "500us", "5m", "1.5h", "0.5d". No suffix means seconds.
* Zero means run forever (useful for process group handling without timeout).
*
* Uses integer math internally (nanosecond precision) to avoid pulling in
* the ~6KB f64::from_str machinery from libstd.
*/Should be (doc comment - appears in rustdoc):
//! Parse duration strings like "30s", "100ms", "500us", "5m", "1.5h", "0.5d".
//!
//! No suffix means seconds. Zero means run forever (useful for process group
//! handling without timeout).
//!
//! Uses integer math internally (nanosecond precision) to avoid pulling in
//! the ~6KB `f64::from_str` machinery from libstd.
Note: This is a quick fix - the content already exists, it just needs to be converted from /* */ to //! format.
Important Distinction:
///and//!are doc comments - generate rustdoc, visible in API docs//and/* */are code comments - only visible in source code
The codebase often uses code comments where doc comments would be more appropriate:
// Current (code comment - not in rustdoc):
/* zero duration = no timeout, run forever */
#[must_use]
pub const fn is_no_timeout(duration: &Duration) -> bool
// Should be (doc comment - appears in rustdoc):
/// Returns `true` if the duration represents "no timeout" (run forever).
#[must_use]
pub const fn is_no_timeout(duration: &Duration) -> boolSome public functions have proper doc comments. Example from duration.rs:
/// Parse "30", "30s", "100ms", "500us", "1.5m", "2h", "0.5d". No suffix = seconds.
///
/// # Examples
///
/// ```
/// use darwin_timeout::duration::parse_duration;
/// use std::time::Duration;
///
/// assert_eq!(parse_duration("30").unwrap(), Duration::from_secs(30));
/// assert_eq!(parse_duration("30s").unwrap(), Duration::from_secs(30));
/// assert_eq!(parse_duration("100ms").unwrap(), Duration::from_millis(100));
/// ```
pub fn parse_duration(input: &str) -> Result<Duration>Clippy pedantic reports:
- Missing
# Errorssections for fallible functions - Missing
# Panicssections (though nothing panics) - Some doc items need backticks
Good Pattern - Error Documentation:
/// # Errors
///
/// - `WaitForFileTimeout` if timeout expires before file appears
/// - `WaitForFileError` if stat() fails with an error other than ENOENT
pub fn wait_for_file(...) -> Result<()>Good Pattern - Safety Invariants:
/// # Safety Invariants
///
/// The state machine guarantees safe access:
/// - `UNINIT`: value is None, safe to write (after winning CAS)
/// - `INITIALIZING`: one thread is writing, others must spin-wait
/// - `INITIALIZED`: value is Some, immutable, safe to read
The project uses both styles appropriately:
/* ... */for multi-line explanations//for single-line notes// SAFETY:for unsafe blocks (required by lint)
Excellent - Explains Why:
/* zero duration = no timeout, run forever */
#[must_use]
pub const fn is_no_timeout(duration: &Duration) -> bool {
duration.is_zero()
}Excellent - Documents Constraint:
/* exit codes per GNU coreutils convention. don't change these. */
pub mod exit_codes {
/// Command ran too long (timed out)
pub const TIMEOUT: u8 = 124;Excellent - Explains Design Decision:
/* stack buffer - no heap allocation */
let mut frac_buf = [b'0'; 9];[lints.clippy]
undocumented_unsafe_blocks = "deny"Good - Explains Preconditions:
// SAFETY: malloc is safe to call with any size. Returns aligned memory for
// alignments <= 16 bytes (guaranteed by macOS malloc). For larger alignments,
// posix_memalign is used which guarantees the requested alignment.
unsafe {
if layout.align() > 16 { ... }
}Good - Explains Invariants:
// SAFETY: We won the CAS race, transitioning UNINIT -> INITIALIZING.
// No other thread can be reading (state wasn't INITIALIZED) or
// writing (we hold the INITIALIZING lock). Safe to write.
unsafe {
*self.value.get() = Some(value);
}Good - References Memory Ordering:
// SAFETY: state is INITIALIZED with Acquire ordering, which synchronizes
// with the Release store in set/get_or_init. The value was written before
// that Release store, so we can safely read it./// # Examples
///
/// ```
/// use darwin_timeout::duration::parse_duration;
/// assert_eq!(parse_duration("30").unwrap(), Duration::from_secs(30));
/// ```
Doctests exist for key public functions and serve as:
- Usage examples
- Regression tests
- Documentation validation
- Add
# Errorssections to fallible functions - Add backticks to inline code in docs
- Add
//!module docs toargs.rsandsignal.rs - Consider adding architecture overview diagram to README
- Add changelog (CHANGELOG.md)
- Add contributing guide
Documentation Quality: Mixed
| Aspect | Rating |
|---|---|
| README | Excellent |
Module docs (//!) |
Missing (content exists as /* */) |
Function docs (///) |
Sparse (content often exists as /* */ or //) |
Code comments (//, /* */) |
Excellent |
| SAFETY comments | Excellent |
| Doctests | Good (where present) |
Key Issue: The codebase has excellent code comments explaining implementation details, but uses regular comments (/* */, //) instead of doc comments (//!, ///). The explanations exist in source but don't appear in cargo doc output.
Quick Fix: Convert existing comments to doc format:
- Module headers:
/* ... */→//! ... - Function comments:
/* ... */or//→/// ...
The content is already written; it just needs the comment style changed.
The SAFETY comments are particularly thorough, which is critical for a project with significant unsafe code.