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

feat(fdtable): add CLOEXEC flag #162

Merged
merged 1 commit into from
Feb 10, 2025
Merged

Conversation

Stone749990226
Copy link

Add support for the CLOEXEC flag in file descriptors.

@Stone749990226 Stone749990226 force-pushed the dev branch 3 times, most recently from 2db9013 to 5ead86a Compare January 16, 2025 17:28
@ken4647 ken4647 self-requested a review January 20, 2025 04:42
modules/ruxtask/src/fs.rs Outdated Show resolved Hide resolved
modules/ruxtask/src/fs.rs Outdated Show resolved Hide resolved
@Stone749990226 Stone749990226 force-pushed the dev branch 2 times, most recently from 7085fad to 8f6e1ef Compare January 21, 2025 09:30
modules/ruxtask/src/fs.rs Outdated Show resolved Hide resolved
@Stone749990226 Stone749990226 force-pushed the dev branch 3 times, most recently from 2bbe4d3 to b4f2490 Compare February 7, 2025 09:49
chore: apply code style fixes and update documentation
@Stone749990226
Copy link
Author

Stone749990226 commented Feb 10, 2025

test script:

main.c:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
    int fd;
    pid_t pid;

    // Create a temporary file
    fd = open("test_file.txt", O_CREAT | O_RDWR, 0644);
    if (fd == -1) {
        perror("open failed");
        exit(EXIT_FAILURE);
    }

    // Print the file descriptor
    printf("Parent process: Opened file descriptor %d\n", fd);

    // Set FD_CLOEXEC flag (Close on exec)
    if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
        perror("fcntl F_SETFD failed");
        close(fd);
        exit(EXIT_FAILURE);
    }

    // Create a child process
    pid = fork();
    if (pid == -1) {
        perror("fork failed");
        close(fd);
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // Child process: Execute another program
        printf("Child process: Executing 'child_test'...\n");
        char fd_str[16];
        snprintf(fd_str, sizeof(fd_str), "%d", fd); // Convert file descriptor to string
        execl("./test_cloexec_child_aarch64", "./test_cloexec_child_aarch64", fd_str, NULL);

        // If execl returns, something went wrong
        perror("execl failed");
        close(fd);
        exit(EXIT_FAILURE);
    } else {
        // Parent process: Wait for the child process to complete
        printf("Parent process: Waiting for child to complete...\n");
        int status;
        waitpid(pid, &status, 0);

        if (WIFEXITED(status)) {
            printf("Parent process: Child exited with status %d\n", WEXITSTATUS(status));
        } else {
            printf("Parent process: Child did not exit normally\n");
        }

        // Cleanup
        close(fd);
        unlink("test_file.txt"); // Delete the temporary file
        printf("Parent process: Done.\n");
    }

    return 0;
}

test_cloexec_child.c: This program is compiled into ./test_cloexec_child_aarch64, which will be called in main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    // Check if the file descriptor is passed as an argument
    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s <fd>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // Convert the argument to an integer (file descriptor)
    int fd = atoi(argv[1]); // Get the file descriptor passed as argument
    printf("Child process: Got file descriptor %d\n", fd);

    // Try to read from the file descriptor
    char buffer[16];
    ssize_t n = read(fd, buffer, sizeof(buffer));

    if (n == -1)
    {
        // If reading fails, it means FD_CLOEXEC is working, and the file descriptor is closed on exec
        perror("Child process: read failed");
        printf("Child process: File descriptor %d is not valid (expected if FD_CLOEXEC works).\n", fd);
        exit(EXIT_SUCCESS);
    }
    else
    {
        // If reading succeeds, something is wrong because the file descriptor should be closed
        printf("Child process: Unexpectedly read %zd bytes from file descriptor %d\n", n, fd);
        exit(EXIT_FAILURE);
    }
}

if CLOEXEC flag works, the output will be:

Parent process: Opened file descriptor 3
Parent process: Waiting for child to complete...
Child process: Executing 'child_test'...
Child process: read failed: Bad file descriptor
child get fd: 3Child process: File descriptor 3 is not valid (expected if FD_CLOEXEC works).
Parent process: Child exited with status 0
Parent process: Done.

else, the output will print:

Parent process: Opened file descriptor 3
Parent process: Waiting for child to complete...
Child process: Executing 'child_test'...
child get fd: 3
Child process: Unexpectedly read 0 bytes from file descriptor 3
Parent process: Child exited with status 1
Parent process: Done.

@ken4647 ken4647 merged commit 154103c into syswonder:dev Feb 10, 2025
9 of 10 checks passed
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