This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: syscalls, libgloss, errno


Jeff, many thanks for your answer !

But there are still things I can't understand.

Let's talk about a very simple configuration. The system is single threaded, so there are no reentrancy issues. The libgloss implementation is the standard libnosys, which returns ENOSYS in every function call.
I am in the configuration #2 from reent.h :
MISSING_SYSCALL_NAMES is not defined
and syscall_dir=syscalls
REENTRANT_SYSCALLS_PROVIDED is not defined


I want to :
- #include <errno.h>
- call fopen() and find ENOSYS in errno
- call open() and find ENOSYS in errno

1) The case of fopen()
fopen() will call _open_r().
_open_r() is implemented in libc/reent/openr.c and calls _open()
_open() is implemented in libgloss/libnosys/open.c

2) The case of open()
open() is implemented in syscalls/sysopen.c and calls _open()
_open() is implemented in libgloss/libnosys/open.c

So in every case, we end up to _open() in libgloss. Good.

Now, let's talk about errno.

_open(), in libnosys, returns the error code in "extern int errno".
This is not a problem because we are on a single threaded environment.

open() just calls _open().
So open() returns the error code in "extern int errno".

_open_r() calls _open(), and copies the error code from "extern int errno" to __errno_r(_REENT). That's good.
So _open_r() returns the error code in __errno_r(_REENT).


fopen() calls _open_r(), and doesn't mess errno.
So fopen() returns the error code in __errno_r(_REENT).

The application #include <errno.h> and uses errno.
In errno.h: #define errno (*__errno())
In errno.c: int * __errno () { return &_REENT->_errno; }
So the application finds the error code in __errno_r(_REENT).

Finally :
When the application calls fopen(), it finds the correct error code in errno.
But when it calls open(), it will not find the error code in errno (which is actually __errno_r(_REENT)), because open() returns the error code into "extern int errno" !


The problem is in the implementation of open() and other syscalls in libc/syscalls/*
If REENTRANT_SYSCALLS_PROVIDED is defined (which is not the case here), open() calls _open_r() and the error is returned into __errno_r(_REENT)) as expected.
But if REENTRANT_SYSCALLS_PROVIDED is not defined (the case here), it should call _open() and translate the error from "extern int errno" to __errno_r(_REENT), just like the implementation of _open_r() does.
Another solution to implement open() would be to unconditionally call _open_r(), just like fopen().


Another good working example is rename(), when HAVE_RENAME.
rename() (in libc/stdio/rename.c) unconditionally calls _rename_r().
_rename_r() (in libc/reent/renamer.c) calls _rename() and translates the error from "extern int errno" to __errno_r(_REENT).
_rename() (provided somewhere in the libgloss implementation) returns the error into "extern int errno".


Conclusion :
Either I misunderstood something, either there is a problem in syscalls/sys*.c. In the latter case, I provided 2 simple solutions.


NB: I found a discussion about this problem in the list archives.
http://www.cygwin.com/ml/newlib/2001/msg00305.html

--
Vincent Rivière


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]