Skip to content
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

Define our own Errno #356

Merged
merged 4 commits into from
Apr 7, 2024
Merged

Define our own Errno #356

merged 4 commits into from
Apr 7, 2024

Conversation

magicant
Copy link
Owner

@magicant magicant commented Apr 7, 2024

This PR is part of #353.

This PR introduces the Errno type that wraps a raw errno value. This new type replaces all uses of nix::errno::Errno except in the following implementations:

  • internals of our Errno type,
  • test harness for the scripted tests, and
  • implementation of RealSystem.

@magicant magicant added the enhancement New feature or request label Apr 7, 2024
@magicant magicant self-assigned this Apr 7, 2024
Copy link

coderabbitai bot commented Apr 7, 2024

Walkthrough

The overarching change across multiple files in the yash-env and yash-semantics modules involves transitioning from using nix::Error to a more specific Errno type for error handling. This move standardizes error handling across the system and semantics layers, improving the clarity and specificity of errors. Functions and methods have been updated to return a custom Result type leveraging Errno, and error messages have been refined to use to_string() for more consistent and readable output.

Changes

Files Summary
src/input.rs, src/system/fd_set.rs, src/system/virtual/io.rs No detailed summary provided.
src/lib.rs, src/pwd.rs, src/semantics.rs, src/subshell.rs, src/system.rs, src/system/real.rs, src/system/virtual.rs, src/system/virtual/file_system.rs, src/command/compound_command/subshell.rs, src/command/item.rs, src/command/pipeline.rs, src/command/simple_command/absent.rs, src/command/simple_command/external.rs, src/expansion.rs, src/redir.rs Transitioned from nix::Error to Errno for error handling, updated function return types to use crate::system::Result and Errno, and refined error messages using to_string().

🐇✨
In the realm of code where errors intertwine,
A rabbit hopped through, making things align.
nix::Error fades, Errno takes its place,
With clearer messages, errors we now face.
Through files and functions, changes bound,
A tale of improvement, in yash found.
🌟🐾

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@magicant magicant mentioned this pull request Mar 22, 2024
17 tasks
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 8ba07d1 and 2165eba.
Files selected for processing (19)
  • yash-env/src/input.rs (2 hunks)
  • yash-env/src/lib.rs (5 hunks)
  • yash-env/src/pwd.rs (3 hunks)
  • yash-env/src/semantics.rs (2 hunks)
  • yash-env/src/subshell.rs (3 hunks)
  • yash-env/src/system.rs (32 hunks)
  • yash-env/src/system/errno.rs (1 hunks)
  • yash-env/src/system/fd_set.rs (1 hunks)
  • yash-env/src/system/real.rs (16 hunks)
  • yash-env/src/system/virtual.rs (30 hunks)
  • yash-env/src/system/virtual/file_system.rs (6 hunks)
  • yash-env/src/system/virtual/io.rs (4 hunks)
  • yash-semantics/src/command/compound_command/subshell.rs (1 hunks)
  • yash-semantics/src/command/item.rs (1 hunks)
  • yash-semantics/src/command/pipeline.rs (4 hunks)
  • yash-semantics/src/command/simple_command/absent.rs (1 hunks)
  • yash-semantics/src/command/simple_command/external.rs (2 hunks)
  • yash-semantics/src/expansion.rs (1 hunks)
  • yash-semantics/src/redir.rs (1 hunks)
Additional comments not posted (59)
yash-env/src/system/fd_set.rs (1)

23-23: LGTM! The import change aligns with the PR's objectives to use a custom Errno type.

yash-semantics/src/command/simple_command/absent.rs (1)

90-90: LGTM! The change to errno.to_string() for error messages aligns with the PR's objectives to enhance error handling.

yash-env/src/pwd.rs (3)

21-21: LGTM! The addition of the Errno import aligns with the PR's objectives to use a custom Errno type.


53-53: LGTM! Changing error handling from nix::Error to Errno in PreparePwdError aligns with the PR's objectives.


105-105: LGTM! Updating error mapping from nix::Error::EILSEQ to Errno::EILSEQ is consistent with the PR's goals.

yash-semantics/src/command/compound_command/subshell.rs (1)

57-57: LGTM! The change to errno.to_string() for error messages aligns with the PR's objectives to enhance error handling.

yash-env/src/semantics.rs (1)

132-137: LGTM! Updating the error type in the TryFrom<ExitStatus> for Signal implementation to use Errno aligns with the PR's objectives.

yash-env/src/input.rs (2)

101-101: LGTM! Updating error handling to use Errno aligns with the PR's objectives.


248-248: LGTM! Adjusting the assertion to use Errno::EBADF.0 is consistent with the PR's goals.

yash-semantics/src/command/item.rs (1)

92-92: LGTM! The update to use errno.to_string().into() aligns with Rust idioms and the PR's objectives for improved error handling.

yash-env/src/system/errno.rs (1)

1-302: LGTM! The Errno type and its associated functionalities are well-defined and align with the PR's objectives for improved error handling.

yash-env/src/system/virtual/file_system.rs (3)

21-21: LGTM! The introduction of Errno aligns with the PR's objectives for improved error handling.


66-66: LGTM! Updating the save method to use Errno for error handling is a positive change.


130-130: LGTM! The update to the get method's return type to use Errno is consistent with the PR's objectives.

yash-semantics/src/command/simple_command/external.rs (2)

133-133: LGTM! Replacing errno.desc() with errno.to_string() standardizes error message formatting.


194-194: LGTM! The update to use errno.to_string() for error messages enhances consistency.

yash-semantics/src/expansion.rs (1)

167-167: LGTM! Using e.to_string() for CommandSubstError improves error message clarity.

yash-env/src/system/real.rs (19)

44-44: Ensure that the alias NixErrno is used consistently throughout the file to refer to nix::errno::Errno.


80-88: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [83-106]

The errno_if_m1 trait method implementation is concise and correctly uses the newly defined Errno type for error handling. This is a good use of traits to provide a common functionality across different types.


174-175: The use of the ? operator for concise error propagation with the custom Result type is appropriate here.


190-192: Creating a pipe and converting the file descriptors to the Fd type is correctly handled. The use of the ? operator simplifies error handling.


204-209: The loop to handle EINTR errors during dup2 is a good practice for robust error handling in system calls. However, consider adding a brief comment explaining why EINTR errors are specifically retried.


218-221: The error handling in open_tmpfile correctly converts a potential None from error.raw_os_error() to 0, aligning with the Errno type's expectations. This is a good example of defensive programming.


225-230: The loop to handle EINTR and EBADF errors during close is correctly implemented. The handling of EBADF by returning Ok(()) is particularly noteworthy, as it gracefully handles a common error scenario.


255-263: The retry logic for read in the presence of EINTR errors is correctly implemented. This pattern is essential for robust system call handling.


277-288: The conversion of SeekFrom to nix::unistd::Whence and the subsequent call to lseek are correctly implemented. The use of try_into for converting u64 to i64 and handling potential overflow with NixErrno::EOVERFLOW is a good practice.


291-299: The handling of fdopendir and opendir with NonNull::new(dir).ok_or_else(NixErrno::last)? is a concise and effective way to handle potential null pointers from these calls.


334-345: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [311-339]

The implementation of times and sigmask methods correctly uses the Errno type for error handling and adheres to best practices for interacting with system calls.


383-393: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [342-390]

The sigaction and kill methods are correctly implemented, with proper error handling and usage of the custom Result type. The async block in kill is a good use of Rust's async features for potentially blocking operations.


396-402: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [399-409]

The implementation of select correctly handles the conversion of Option<&TimeSpec> and Option<&SigSet> to raw pointers, and the use of errno_if_m1 for error handling is consistent with the rest of the file.


424-436: The methods setpgid, tcgetpgrp, and tcsetpgrp are correctly implemented, with concise error handling using the custom Result type.


460-497: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [446-467]

The new_child_process and wait methods are correctly implemented, showcasing good practices in error handling and process management.


470-475: The retry logic for execve in the presence of EINTR errors is correctly implemented, ensuring robust handling of system calls.


480-486: The methods getcwd and chdir are correctly implemented, with concise and effective error handling using the custom Result type.


489-491: The method getpwnam_dir correctly handles potential errors from nix::unistd::User::from_name and gracefully converts the result to an Option<std::path::PathBuf>.


539-546: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [494-543]

The confstr_path, getrlimit, and setrlimit methods are correctly implemented, with appropriate error handling and usage of the custom Result type. The handling of platform-specific behavior in confstr_path is a good example of conditional compilation.

yash-semantics/src/command/pipeline.rs (4)

146-147: The refactoring to construct the error message before calling print_error in execute_job_controlled_pipeline improves readability and maintainability.


196-197: The refactoring in shift_or_fail to construct the error message before calling print_error is consistent with the changes in execute_job_controlled_pipeline and improves code readability.


212-213: Similar to the previous comments, the refactoring in connect_pipe_and_execute_command to construct the error message before calling print_error enhances the clarity of the error handling logic.


235-235: Simplifying the error message formatting in pid_or_fail by directly using the errno value is a good practice, ensuring that the error messages are concise and to the point.

yash-env/src/system/virtual/io.rs (2)

113-113: Ensure proper documentation for the read function's behavior with the new Errno return type.


210-210: Verify the handling of Whence::SeekHole and Whence::SeekData in the seek function, as they are currently unsupported.

Verification successful

To further verify the handling of Whence::SeekHole and Whence::SeekData in the seek function, we need to inspect the implementation of the seek function directly. Let's proceed with that.


The implementation of the seek function in yash-env/src/system/virtual/io.rs confirms that Whence::SeekHole and Whence::SeekData are indeed unsupported. For these cases, along with any other unhandled Whence values, the function returns an Errno::EINVAL error, aligning with the initial review comment.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Ensure no code paths rely on unsupported Whence::SeekHole or Whence::SeekData.
rg "SeekHole|SeekData"

Length of output: 108



Script:

#!/bin/bash
# Inspect the implementation of the seek function in yash-env/src/system/virtual/io.rs
cat yash-env/src/system/virtual/io.rs | grep -A 20 "pub fn seek"

Length of output: 939

yash-env/src/lib.rs (2)

336-336: Add error handling documentation for wait_for_subshell to clarify expected Errno values.


360-360: Consider implementing a timeout mechanism for wait_for_subshell_to_finish to prevent indefinite waiting.

yash-env/src/subshell.rs (3)

33-33: Import of Errno aligns with the PR's objective to utilize the custom Errno type for error handling.


154-154: The update to the start function's signature to use the custom Errno type improves error handling and type safety.


242-242: The update to the start_and_wait function's signature to use the custom Errno type is consistent with the PR's objectives, enhancing error handling and type safety.

yash-semantics/src/redir.rs (6)

194-194: Consider providing more descriptive error messages for FdNotOverwritten errors.

The current implementation directly converts the errno to a string for the error message. While this is technically correct, it might not provide enough context for users to understand the error. Consider appending a more descriptive message before the errno string to clarify the nature of the error.


196-196: Ensure consistent error message formatting for OpenFile errors.

The error message for OpenFile errors combines the path and the errno directly. This is consistent with the other changes, but consider if additional context or formatting could make these messages clearer or more user-friendly.


200-200: Use descriptive error messages for TemporaryFileUnavailable errors.

Similar to the FdNotOverwritten error, the message for TemporaryFileUnavailable errors directly uses the errno string. It might be beneficial to prepend a descriptive message to provide more context about the error, especially since temporary file creation issues can stem from various system limitations or configurations.


Line range hint 1-1: Verify the license compatibility and adherence.

Ensure that the use of the GNU General Public License (GPL) for this file is compatible with the rest of the project's licensing and that it adheres to the GPL's requirements. This is especially important if the project is intended to be used as a library or incorporated into other software.


Line range hint 1-1: Consider adding module-level documentation.

The file lacks module-level documentation that explains its purpose and how it fits into the larger project. Adding a brief overview at the beginning of the file could improve maintainability and help new contributors understand the role of this module in the context of the project.


Line range hint 1-1: Evaluate the use of async in file operations.

The use of async functions for file operations, such as open_normal, is interesting but requires careful consideration. Ensure that the asynchronous operations are truly beneficial and do not introduce unnecessary complexity or performance overhead, especially since file I/O can often be blocking by nature.

yash-env/src/system.rs (1)

118-171: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [94-1004]

Updated function signatures to use the local Result type instead of nix::Result. This change is crucial for integrating the custom Errno type across the system's API, enhancing type safety and error handling consistency. Verify that all instances where nix::Result was previously used have been updated accordingly and that error handling logic has been adapted to work with the new Errno type.

yash-env/src/system/virtual.rs (5)

67-67: Consider documenting the purpose of the Result type alias within the context of VirtualSystem.

Adding a comment explaining that Result is a custom result type specific to the virtual system's error handling could improve code readability and maintainability.


219-221: Ensure proper documentation for the closure parameter F in with_open_file_description.

Adding a brief comment describing the expected behavior or purpose of the closure F can enhance code readability and maintainability, especially for complex closures.


232-234: Similar to the previous comment, ensure proper documentation for the closure parameter F in with_open_file_description_mut.


1256-1256: Ensure the Executor trait's spawn method is documented, especially regarding its return values.

Documenting the expected outcomes of the spawn method, including potential errors, can aid in understanding and using this trait effectively.


930-930: Clarify the TODO comment in the wait method regarding supported target values.

Expanding on the TODO comment to specify what needs to be implemented or changed for unsupported target values can guide future development efforts.

Comment on lines +19 to +27
mod errno;
pub mod fd_set;
pub mod real;
pub mod resource;
pub mod r#virtual;

pub use self::errno::Errno;
pub use self::errno::RawErrno;
pub use self::errno::Result;
Copy link

Choose a reason for hiding this comment

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

Introduced errno module and re-exported Errno, RawErrno, and Result types. This aligns with the PR's objective to enhance error handling and type safety by encapsulating errno values within a custom type. Ensure that the Errno type and its associated functionalities are thoroughly tested, especially the conversions between Errno and other error types like std::io::Error.

Comment on lines 700 to 714

fn reset_nonblocking(&mut self, fd: Fd, old_flags: OFlag) {
if !old_flags.contains(OFlag::O_NONBLOCK) {
let _: Result<(), _> = self.0.borrow_mut().system.fcntl_setfl(fd, old_flags);
let _: Result<()> = self.0.borrow_mut().system.fcntl_setfl(fd, old_flags);
}
}

/// Reads from the file descriptor.
///
/// This function waits for one or more bytes to be available for reading.
/// If successful, returns the number of bytes read.
pub async fn read_async(&mut self, fd: Fd, buffer: &mut [u8]) -> nix::Result<usize> {
pub async fn read_async(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize> {
let flags = self.set_nonblocking(fd)?;

// We need to retain a strong reference to the waker outside the poll_fn
Copy link

Choose a reason for hiding this comment

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

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [692-746]

Implemented asynchronous read and write operations in SharedSystem using non-blocking I/O and futures. This approach is essential for supporting concurrent I/O in an async function context. Ensure that error handling in these asynchronous operations correctly handles EAGAIN and EINTR errors by retrying the operation, and that the non-blocking flag is properly managed to avoid altering the expected behavior of file descriptors outside these operations.

Comment on lines 1071 to 1077
}

/// Calls `sigmask` and updates `self.wait_mask`.
fn sigmask(&mut self, how: SigmaskHow, signal: Signal) -> nix::Result<()> {
fn sigmask(&mut self, how: SigmaskHow, signal: Signal) -> Result<()> {
let mut set = SigSet::empty();
let mut old_set = SigSet::empty();
set.add(signal);
Copy link

Choose a reason for hiding this comment

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

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [1026-1093]

Enhanced signal handling with set_signal_handling and related functions. This change is part of the effort to improve the system's responsiveness and reliability by properly managing signal handling in an asynchronous context. Ensure that signal handling setup, including blocking and unblocking signals and setting signal actions, is correctly implemented to avoid race conditions or missed signals. Additionally, verify that the signal handling changes do not interfere with the system's existing signal handling mechanisms outside of SharedSystem.

Comment on lines +56 to +67
// TODO Need nix 0.28.0
// /// Sets the current `errno` value.
// ///
// /// This function sets the current `errno` value to the specified value.
// /// The next call to [`last`](Self::last) will return the specified value
// /// unless another system call changes the `errno` value. This function is
// /// useful when you want to simulate an error condition in a system call.
// ///
// /// Use [`clear`](Self::clear) to reset the `errno` value.
// pub fn set_last(errno: Self) {
// nix::Error::set_raw(errno.0)
// }
Copy link

Choose a reason for hiding this comment

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

Consider tracking the implementation of set_last() method with a GitHub issue once the nix dependency is updated to version 0.28.0.

Would you like me to open a GitHub issue for this?

@@ -251,7 +252,7 @@ impl VirtualSystem {
_dir_fd: Fd,
path: &Path,
flags: AtFlags,
) -> nix::Result<Rc<RefCell<INode>>> {
) -> Result<Rc<RefCell<INode>>> {
Copy link

Choose a reason for hiding this comment

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

Handle TODO for resolving relative paths based on dir_fd.

This TODO indicates a missing feature that could affect the correctness of path resolution in certain scenarios. Would you like assistance in implementing this feature?

@@ -541,37 +542,37 @@
}

/// Current implementation does nothing but return `Ok(())`.
fn fcntl_setfl(&mut self, _fd: Fd, _flags: OFlag) -> nix::Result<()> {
fn fcntl_setfl(&mut self, _fd: Fd, _flags: OFlag) -> Result<()> {
Copy link

Choose a reason for hiding this comment

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

Address the TODO in fcntl_setfl to implement the function's intended behavior.

Leaving this function unimplemented might lead to unexpected behavior in tests relying on file descriptor flags being set correctly. If needed, I can help with the implementation.

@@ -156,7 +156,7 @@ impl OpenFileDescription {
/// Writes to this open file description.
///
/// Returns the number of bytes successfully written.
pub fn write(&mut self, mut buffer: &[u8]) -> nix::Result<usize> {
pub fn write(&mut self, mut buffer: &[u8]) -> Result<usize, Errno> {
Copy link

Choose a reason for hiding this comment

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

Consider adding unit tests for the write function to cover scenarios with different Errno values.

Would you like me to help by adding some unit tests for this function?

yash-env/src/lib.rs Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 8ba07d1 and 8c24b79.
Files selected for processing (19)
  • yash-env/src/input.rs (2 hunks)
  • yash-env/src/lib.rs (5 hunks)
  • yash-env/src/pwd.rs (3 hunks)
  • yash-env/src/semantics.rs (2 hunks)
  • yash-env/src/subshell.rs (3 hunks)
  • yash-env/src/system.rs (32 hunks)
  • yash-env/src/system/errno.rs (1 hunks)
  • yash-env/src/system/fd_set.rs (1 hunks)
  • yash-env/src/system/real.rs (16 hunks)
  • yash-env/src/system/virtual.rs (30 hunks)
  • yash-env/src/system/virtual/file_system.rs (6 hunks)
  • yash-env/src/system/virtual/io.rs (4 hunks)
  • yash-semantics/src/command/compound_command/subshell.rs (1 hunks)
  • yash-semantics/src/command/item.rs (1 hunks)
  • yash-semantics/src/command/pipeline.rs (4 hunks)
  • yash-semantics/src/command/simple_command/absent.rs (1 hunks)
  • yash-semantics/src/command/simple_command/external.rs (2 hunks)
  • yash-semantics/src/expansion.rs (1 hunks)
  • yash-semantics/src/redir.rs (1 hunks)
Files skipped from review as they are similar to previous changes (18)
  • yash-env/src/input.rs
  • yash-env/src/lib.rs
  • yash-env/src/pwd.rs
  • yash-env/src/semantics.rs
  • yash-env/src/subshell.rs
  • yash-env/src/system.rs
  • yash-env/src/system/errno.rs
  • yash-env/src/system/fd_set.rs
  • yash-env/src/system/virtual.rs
  • yash-env/src/system/virtual/file_system.rs
  • yash-env/src/system/virtual/io.rs
  • yash-semantics/src/command/compound_command/subshell.rs
  • yash-semantics/src/command/item.rs
  • yash-semantics/src/command/pipeline.rs
  • yash-semantics/src/command/simple_command/absent.rs
  • yash-semantics/src/command/simple_command/external.rs
  • yash-semantics/src/expansion.rs
  • yash-semantics/src/redir.rs
Additional comments not posted (13)
yash-env/src/system/real.rs (13)

44-44: The import of nix::errno::Errno as NixErrno is necessary due to the selective retention of nix::errno::Errno for specific use cases. Ensure that this import is used consistently throughout the file.


80-88: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [83-106]

The errno_if_m1 trait method correctly converts a result of -1 to an Error with the current errno, leveraging the newly introduced Errno type. This is a good use of Rust's traits to provide a common functionality across different numeric types.


208-209: The handling of NixErrno::EINTR in a loop for retrying system calls is a best practice for dealing with interruptions. This pattern is correctly applied in the dup2 method.


221-221: When handling errors in open_tmpfile, ensure that Errno(error.raw_os_error().unwrap_or(0)) is the best way to convert the error. Consider if there's a more descriptive default error than 0 in case raw_os_error() returns None.


228-230: The handling of NixErrno::EBADF and NixErrno::EINTR in the close method is appropriate. Returning Ok(()) for EBADF might be acceptable depending on the project's error handling strategy, but ensure this behavior is documented.


259-272: The retry logic for read and write methods in the presence of NixErrno::EINTR is correctly implemented. This ensures robustness in system call handling.


281-281: In lseek, converting the offset to c_int and handling EOVERFLOW is a good practice to ensure the call's safety. This prevents potential issues with large offsets.


293-299: The use of NonNull::new(dir).ok_or_else(NixErrno::last)? in fdopendir and opendir methods is a concise way to handle potential null pointers from C library calls.


337-339: The implementation of sigmask using nix::sys::signal::sigprocmask directly and returning a simple Ok(()) upon success is straightforward and clear.


387-390: The use of async block in kill method is an interesting approach to potentially blocking operations. Ensure that this fits well with the overall asynchronous design of the system.

Verification successful

The script output indicates that the use of async move blocks is a common pattern within the yash-env/src/system module, suggesting that the asynchronous design is consistently applied across the system. This supports the notion that the use of an async move block in the kill method aligns with the overall asynchronous design of the system.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify the usage of async blocks in potentially blocking operations across the project.
rg --type rust 'async move' yash-env/src/system

Length of output: 1087


409-409: The errno_if_m1 method is correctly used in select to handle -1 results, showcasing the utility of the ErrnoIfM1 trait for error handling in system calls.


542-543: The use of errno_if_m1 in setrlimit to handle potential errors is consistent with the rest of the file. This maintains the uniformity in error handling.


560-565: The implementation of next in RealDir correctly handles directory reading and error checking. The use of Errno::clear() before the call and checking Errno::last() after is a good practice.

@@ -30,6 +30,7 @@ use super::FdSet;
use super::FileStat;
use super::Mode;
use super::OFlag;
use super::Result;
Copy link

Choose a reason for hiding this comment

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

Group use statements for better readability.

use super::{Result, SigSet, SigmaskHow, Signal, System, TimeSpec, Times};

Comment on lines 187 to 302
Err(Errno::EINTR) => (),
other => return other,
Err(NixErrno::EBADF) => return Ok(()),
Err(NixErrno::EINTR) => (),
other => return Ok(other?),
}
}
}

fn fcntl_getfl(&self, fd: Fd) -> nix::Result<OFlag> {
nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_GETFL).map(OFlag::from_bits_truncate)
fn fcntl_getfl(&self, fd: Fd) -> Result<OFlag> {
let bits = nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_GETFL)?;
Ok(OFlag::from_bits_truncate(bits))
}

fn fcntl_setfl(&mut self, fd: Fd, flags: OFlag) -> nix::Result<()> {
nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_SETFL(flags)).map(drop)
fn fcntl_setfl(&mut self, fd: Fd, flags: OFlag) -> Result<()> {
let _ = nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_SETFL(flags))?;
Ok(())
}

fn fcntl_getfd(&self, fd: Fd) -> nix::Result<FdFlag> {
nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_GETFD).map(FdFlag::from_bits_truncate)
fn fcntl_getfd(&self, fd: Fd) -> Result<FdFlag> {
let bits = nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_GETFD)?;
Ok(FdFlag::from_bits_truncate(bits))
}

fn fcntl_setfd(&mut self, fd: Fd, flags: FdFlag) -> nix::Result<()> {
nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_SETFD(flags)).map(drop)
fn fcntl_setfd(&mut self, fd: Fd, flags: FdFlag) -> Result<()> {
let _ = nix::fcntl::fcntl(fd.0, nix::fcntl::FcntlArg::F_SETFD(flags))?;
Ok(())
}

fn isatty(&self, fd: Fd) -> nix::Result<bool> {
nix::unistd::isatty(fd.0)
fn isatty(&self, fd: Fd) -> Result<bool> {
Ok(nix::unistd::isatty(fd.0)?)
}

fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> nix::Result<usize> {
fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result<usize> {
loop {
let result = nix::unistd::read(fd.0, buffer);
if result != Err(Errno::EINTR) {
return result;
if result != Err(NixErrno::EINTR) {
return Ok(result?);
}
}
}

fn write(&mut self, fd: Fd, buffer: &[u8]) -> nix::Result<usize> {
fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result<usize> {
loop {
let result = nix::unistd::write(fd.0, buffer);
if result != Err(Errno::EINTR) {
return result;
if result != Err(NixErrno::EINTR) {
return Ok(result?);
}
}
}

fn lseek(&mut self, fd: Fd, position: SeekFrom) -> nix::Result<u64> {
fn lseek(&mut self, fd: Fd, position: SeekFrom) -> Result<u64> {
use nix::unistd::Whence::*;
let (offset, whence) = match position {
SeekFrom::Start(offset) => {
let offset = offset.try_into().map_err(|_| Errno::EOVERFLOW)?;
let offset = offset.try_into().map_err(|_| NixErrno::EOVERFLOW)?;
(offset, SeekSet)
}
SeekFrom::End(offset) => (offset, SeekEnd),
SeekFrom::Current(offset) => (offset, SeekCur),
};
nix::unistd::lseek(fd.0, offset, whence).map(|new_offset| new_offset as u64)
let new_offset = nix::unistd::lseek(fd.0, offset, whence)?;
Ok(new_offset as u64)
}

fn fdopendir(&mut self, fd: Fd) -> nix::Result<Box<dyn Dir>> {
fn fdopendir(&mut self, fd: Fd) -> Result<Box<dyn Dir>> {
let dir = unsafe { nix::libc::fdopendir(fd.0) };
let dir = NonNull::new(dir).ok_or_else(Errno::last)?;
let dir = NonNull::new(dir).ok_or_else(NixErrno::last)?;
Ok(Box::new(RealDir(dir)))
}

fn opendir(&mut self, path: &CStr) -> nix::Result<Box<dyn Dir>> {
fn opendir(&mut self, path: &CStr) -> Result<Box<dyn Dir>> {
let dir = unsafe { nix::libc::opendir(path.as_ptr()) };
let dir = NonNull::new(dir).ok_or_else(Errno::last)?;
let dir = NonNull::new(dir).ok_or_else(NixErrno::last)?;
Ok(Box::new(RealDir(dir)))
}

Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The verification process has identified that std::io::Result is still being used in the getrlimit and setrlimit functions within the yash-env/src/system/real.rs file, which contradicts the requirement to use the project's Result type exclusively for system calls. This confirms the validity of the review comment.

Analysis chain

📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [174-252]

Ensure that all system calls now correctly use the project's Result type instead of std::io::Result or nix::Result. This change is crucial for maintaining consistency in error handling across the project.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that `std::io::Result` and `nix::Result` are no longer used in favor of the project's `Result` type.
rg --type rust 'std::io::Result|nix::Result' yash-env/src/system/real.rs

Length of output: 242

yash-env/src/system/real.rs Show resolved Hide resolved
@magicant magicant merged commit 86030d9 into master Apr 7, 2024
5 checks passed
@magicant magicant deleted the env-error branch April 7, 2024 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

1 participant