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

[Feature Request] Errno Getter #3921

Open
1 task done
owenhilyard opened this issue Jan 2, 2025 · 2 comments
Open
1 task done

[Feature Request] Errno Getter #3921

owenhilyard opened this issue Jan 2, 2025 · 2 comments
Labels
enhancement New feature or request mojo-repo Tag all issues with this label

Comments

@owenhilyard
Copy link
Contributor

Review Mojo's priorities

What is your request?

A getter for errno, likely in the form fn raw_errno() -> c_int as a runtime builtin.

What is your motivation for this change?

Many, many, many POSIX functions use errno to return error codes, and checking it is necessary for proper error handling. We can't give coherent errors to the user without this. As far as I am aware, there is no way to access a C global variable from Mojo, so it needs to be a runtime builtin.

Any other details?

The reason I'm asking for raw_errno is so we can wrap the function with something that returns an enum for an easier to use "errno" function. A general version of this solution would be a way to use C ABI globals directly by symbol name, such as some kind of "extern" variable modifier.

@owenhilyard owenhilyard added enhancement New feature or request mojo-repo Tag all issues with this label labels Jan 2, 2025
@martinvuyk
Copy link
Contributor

@owenhilyard I found a hacky way using the macros. I use it a lot in the PR where I want to add Libc

    fn get_errno(self) -> C.int:
        """Get a copy of the current value of the `errno` global variable for
        the current thread.

        Returns:
            A copy of the current value of `errno` for the current thread.
        """

        @parameter
        if os_is_windows():
            var errno = stack_allocation[1, C.int]()

            @parameter
            if static:
                _ = external_call["_get_errno", C.void](errno)
            else:
                _ = self._lib.value().call["_get_errno", C.void](errno)
            return errno[]
        else:
            alias loc = "__error" if os_is_macos() else "__errno_location"

            @parameter
            if static:
                return external_call[loc, UnsafePointer[C.int]]()[]
            else:
                return self._lib.value().call[loc, UnsafePointer[C.int]]()[]

    fn set_errno(self, errno: C.int):
        """Set the `errno` global variable for the current thread.

        Args:
            errno: The value to set `errno` to.
        """

        @parameter
        if os_is_windows():

            @parameter
            if static:
                _ = external_call["_set_errno", C.int](errno)
            else:
                _ = self._lib.value().call["_set_errno", C.int](errno)
        else:
            alias loc = "__error" if os_is_macos() else "__errno_location"

            @parameter
            if static:
                _ = external_call[loc, UnsafePointer[C.int]]()[0] = errno
            else:
                _ = self._lib.value().call[loc, UnsafePointer[C.int]]()[
                    0
                ] = errno

@owenhilyard
Copy link
Contributor Author

@martinvuyk This should work as a stopgap. I think this is non-portable between libcs on Linux, but that's a "later" problem. However, I'd still like the runtime builtin for portability reasons so we don't need to handle every wacky libc on Linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request mojo-repo Tag all issues with this label
Projects
None yet
Development

No branches or pull requests

2 participants