[Python-Dev] Assign to errno allowed?

Guido van Rossum guido@python.org
Tue, 24 Sep 2002 21:29:19 -0400


[Brad, would you mind limiting your messages to lines of about 72
characters at most?]

> I guess then the best solution is a distinct CVS for "the port to
> oddball platforms"
> 
> or, the other option is lots of #ifdefs in the code.
> 
> The original reason I proposed the macro idea was to eliminate
> multiple nested #ifdefs.. 
> 
> For example, I had trouble figuring out nested #ifdefs in
> posixmodule, as generated by Mark in his CE port.. It's awful.
> 
> By switching to macros for "errno =" I was able to clean up a lot of
> the #ifdefs

Absolutely.  *If* you want to tackle this, macros for setting errno
are the way to go.

> If changes for CE (and other errno-less OS's) are to be kept in the
> core, then we'll either have (from Modules/cpickle.c)
> 
> #ifndef	WINDOWCE
> 	errno = 0;
> #else
> 	SetLastError(0);
> #endif
> 	l = strtol(s, &endptr, 0);
> 
> #ifndef	WINDOWSCE
> 	if (errno || (*endptr != '\n') || (endptr[1] != '\0')) {
> #else
> 	if (GetLastError() || (*endptr != '\n') || (endptr[1] != '\0')) {
> #endif
> 		/* Hm, maybe we've got something long.  Let's try reading
> 		   it as a Python long object. */
> #ifndef	WINDOWSCE
> 		errno = 0;
> #else
> 		SetLastError(0);
> #endif
> 
> ---  Or ---
> 
> 	Py_SetErrno(0)
> 	l = strtol(s, &endptr, 0);
> 
> 	if (Py_GetErrno() || (*endptr != '\n') || (endptr[1] != '\0')) {
> 		/* Hm, maybe we've got something long.  Let's try reading
> 		   it as a Python long object. */
> 		Py_SetErrno(0);

Question.  You showed that errno was #defined as a call to the right
function.  Why don't you leave *getting* errno alone?

You talk of 100s of places using errno.  But how many places *set*
errno?

> Keeping in mind that adding NetWare or (other embedded OS or BIOS
> that wants to play) then the #ifdef version gets much worse.  The
> macro version doesn't change.

Brad, nobody said they preferred the #ifdef version over the macro!
The question is simply whether to use the macro or keep using errno,
in tune with Standard C.

> There are approximately 140 references to errno in the Modules
> directory alone. For the Alpha port of Python 2.2 to CE I changed
> every one of them (at least for any module that could run on CE,
> which is just about everything that runs on Win32)
> 
> I've already said that I've made these changes and am willing to
> make them all again.  Once they're in there, how difficult will it
> be to keep them?

Experience shows that each new release will be broken for your
platform anyway unless you actively maintain it as we gear up for a
release.  Even between alpha or beta releases the code base is likely
to change in some subtle way that breaks your release.  So you'll have
to chase down new uses of errno assignment leading up to each release.

> New code that uses errno will fail on subsequent builds on these
> errno-less platforms, but there will only be a handful of changes
> needed, rather than hundreds on every release of the core.

If you maintain a branch that uses the errno macro, you could merge
the trunk into that branch each time you feel like synching up with
the trunk.  That's a mostly mechanical process, certainly less than
fixing 100s of errno uses manually each time.

Or you could simply maintain a patch in the form of a context diff
that patches the 100s of places using errno -- assuming this is mostly
in stable code, you'd only have to fix up a handful of new occurrences
and places where the patch context has gotten out of sync.

> So .. developers who just write "errno = " in the future won't be
> penalized, rather the porters to errno-less platforms will just have
> to convert the expression to macro mode.

They *would* be penalized, because you have to fix their code, and
then they have to test it again, etc.  It's yet one more thing to
worry about.

> And that conversion process isn't a hardship if it only has to be
> done once for any given line of code on any given core release.. But
> if we (porters) have to change 140 references every single time
> there's a release.. I could see enthusiasm fading away faster than
> those errno-less platforms ;-)
> 
> Clearly you guys know what's best better than I do. My line of
> reasoning for errno macros was:
> 
> 1. on most platforms the macros compile away to what you'd write in
>    C anyway
> 
> 2. I'd generate and submit all the initial patches to the core to
>    switch errno references to macros, leaving the burden of review
>    and checkin to the core team (sorry) but not the burden of
>    finding and changing all errno references

That's another problem.  Whenever there's a massive "peephole" change
like this, there are always a few places that are broken but that no
reviewer notices and that don't happen to be tested by the test suite.
(After all, errno is only consulted when an error occurs, and some
errors are darn hard to provoke.)

> 3. But once the patches are in-place, future releases wouldn't
>    require nearly as much effort for re-port's to errno-less
>    platforms because only a few lines would need to be "fixed up" to
>    use macros, and only if the changed code didn't use the macros in
>    the first place.
> 
> 4. Not using the macros in core or extension source isn't an issue
>    for any platform, except errno-less OS's.. at which time that
>    code gets macro'ized at the time of the port.
> 
> 5. What this does is reduces effort for future ports to crippled
>    systems, at the expense of many initial changes, whose subsequent
>    maintenence shouldn't (hopefully) be a burden, since ports to
>    crippled systems would maintain the changes.
> 
> Though I do agree, a future mismash of macro's and direct errno
> references in the core will be ugly and confusing if that occurs.
> 
> (sorry this is so long, just want to clearly state my case if I have
> not already done so)

I totally understand your case.  I just don't like having to avoid
something that's legal according to the C Standard because of backward
platforms.  Sure, there were platform-specific changes for many other
minority platforms.  But none of then AFAIK required us to change
something that's Standard C -- these changes were usually about
system calls or filename conventions.  And we bend over for Win32
because it's the dominant platform.  For handhelds, I expect that
WinCE will be replaced by something less broken soon.

--Guido van Rossum (home page: http://www.python.org/~guido/)