Skip to content

feat(fdtable): add CLOEXEC flag#162

Merged
ken4647 merged 1 commit into
syswonder:devfrom
Stone749990226:dev
Feb 10, 2025
Merged

feat(fdtable): add CLOEXEC flag#162
ken4647 merged 1 commit into
syswonder:devfrom
Stone749990226:dev

Conversation

@Stone749990226
Copy link
Copy Markdown
Contributor

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
Comment thread modules/ruxtask/src/fs.rs Outdated
Comment thread modules/ruxtask/src/fs.rs Outdated
@Stone749990226 Stone749990226 force-pushed the dev branch 2 times, most recently from 7085fad to 8f6e1ef Compare January 21, 2025 09:30
Comment thread modules/ruxtask/src/fs.rs Outdated
@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
Copy Markdown
Contributor 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
@ken4647 ken4647 mentioned this pull request Jul 22, 2025
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