[fpc-devel] Weird output from fpGetErrNo

Marco van de Voort marcov at stack.nl
Wed Jan 30 23:34:50 CET 2013


In our previous episode, Ewald said:
> > Well, the surprise is that initc worked, and yours not. From a quick glance
> > I believe it to be correct too.
> 
> I believe there is a bit of confusion:

Ok, cler.

> The function that seemingly doesn't work is the native
> fpGetErrNo (with native I mean the function that is available in unit
> baseunix without any modification).
 
That only works for routines that call the FPC syscall.do_syscall function
directly or indirectly.

Just like cerrno works for functions that call libc functions directly or
indirectly.

> That's handy, so it would be advisory to use fperrno as much as possible
> then.

Use fperrno for FPC predeclared functions. That works.
 
> > fpcerrno is always linking to libc's errno.
> > 
> > On platforms where FPC uses libc to acces the kernel, errno=cerrno.
> 
> Thus on linux fpc does its own kernel access then, since errno <> cerrno?

Yes. Free/Open/NetBSD too. The other *nixes (Haiku,Solaris, Darwin/OSX) fall
in the other category.
 
> So, on this linux, after calling a syscall which I defined as `external
> 'c'` 

Not a syscall, but a libc call.  Even though it might call a syscall
internally.

On most *nixes, the kernel returns the error result in some register.  The
wrapper code is responsible for properly storing the error result in some
variable (and nowdays, preferably in a threadsafe manner)

So libc syscll wrapper code stores in the "c" errno, and routines that call
the FPC internal syscall wrapper store it in the RTL errno variable.

>(like the madvise in the original post) it makes no sense to call
> fpGetErrno, and instead I should call fpgetCerrno to get sensible results?

Correct. Or write madvise out as a true syscall, calling syscall.do_syscall
(if there is any). Not all libc calls are direct syscalls.
 
> If the above is right, than errno (without the `C`) contains a leftover
> error from somewhere before in the program. 

All errno's are not cleared in any way, but should be checked _only_ if a
function returns a value that indicates so (usually -1 but sometimes null)

> What bothers me is: what (and why) created the contition? 

You can't know. Any library call might call several other functions that
update errno internally. Schematically, it could be like this:

function somelibccall(aparam:integer):cint;
begin
  if aparam=0 then
    exit(somefunc(aparam))
  else
    begin
      if aparam>10 then
        begin
          errno:=einval;
          exit(-1);
        end;
      result:=somefunc2(aparam);
      if result=-1 then
       begin
         result:=somefunc3(aparam+1);
         if (result=-1) and (errno=einsomething) then
             seterrno(einsomethingelse);
    end;
end;
  
All three somefuncs might write errno, and somelibccall simply passes the
result of those calls on (and leaves their error unmodified, except in the
last case). Moreover, it can write errno from nowwhere.

In such cases it is impossible to tell what of these cases happened from
the result of somelibccall and errno.






More information about the fpc-devel mailing list