[squid-dev] [PATCH] avoid clobbering errno in debugs()
Amos Jeffries
squid3 at treenet.co.nz
Sun Jul 12 06:12:00 UTC 2015
On 12/07/2015 5:45 p.m., Kinkie wrote:
> On Sun, Jul 12, 2015 at 2:34 AM, Amos Jeffries <squid3 at treenet.co.nz> wrote:
>
>> On 12/07/2015 5:42 a.m., Kinkie wrote:
>>> Hi all,
>>> this patch saves and restores errno around calls to strftime in
>>> debugLogTime, preventing harmless errors in these calls from clobbering
>>> errno, thus messing up xstrerror() calls within debugs().
>>>
>>
>> 1) xerrno is a local variable in lots of places in the code. This patch
>> introduces shadowing errors. Please call it debug_xerrno.
>>
>
> Ok, no problem.
>
>
>> 2) The snprintf() call directly after restoring errno in the top chunk
>> may alter the original errno in rare cases as well.
>>
>
> Are you sure? The snprintf manual page doesn't mention that.
>
>
>> Which is a good example of why we simply can't rely on errno being
>> correct for any length of time in C++. Things such as errno changes by
>> operator<< implementations, print() methods, implicit calls to copy
>> constructors/destructors, and exlicit function/method calls are also
>> possible in ways we are unlikely to be predict.
>>
>>
>> We are still going to have to do a global removal of xstrerror() anyway.
>>
>
> I do not object on the technical merit.
> At the same time, there are too many to do it incrementally, and we already
> failed to reach a consensus on flag-day commit for HERE removal. Sure,
> maybe xstrerror()+HERE removal will reach a mass critical enough to support
> the flag-day-commit camp, but I don't see that happening, and we already
> have quite a but of rework due to HERE being left in changed code. We'd end
> up for years with a half-done migration.
>
>
>> IMO, we should move xstrerror() to Debugs.h and make it use the
>> debug_xerrno local variable instead of errno.
>>
>
> Maybe we could change debugLogTime to return a std::string instead of a
> const char *, and format it ourselves using a stringbuf instead of using
> strftime. Or we could maybe do something like this:
>
> int _squid_errno;
> const char *xstrerror() {
> return xstrerr(_squid_errno);
> }
Since this is in a header the function needs to be explicitly 'inline'.
The variable needs explict extern with debug.cc safe initialization, etc.
Far simpler and nicer to leave it as a macro:
#define xstrerror() xstrerr(_sauid_errno)
where _squid_errno as a local to the if-statement scope below.
> #define debugs(SECTION, LEVEL, CONTENT) \
> do { \
> if ((Debug::level = (LEVEL)) <= Debug::Levels[SECTION]) { \
> Debug::sectionLevel = Debug::Levels[SECTION]; \
> _squid_errno = errno;
> std::ostream &_dbo=Debug::getDebugOut(); \
> if (Debug::level > DBG_IMPORTANT) \
> _dbo << SkipBuildPrefix(__FILE__)<<"("<<__LINE__<<")
> "<<__FUNCTION__<<": "; \
> _dbo << CONTENT; \
> Debug::finishDebug(); \
> } \
> } while (/*CONSTCOND*/ 0)
>
> This would make xstrerror only work within debugs(); maybe we could add a
> guard against it by setting _squid_errno to some invalid value and checking
> it in xstrerror. Yes, it's ugly.
Yes, which is why I requested xstrerror() move to Debug.h as part of the
change. The code not using debugs() can and should use xstrerr(foo) instead.
>
> But until we reach a consensus, I'd like authorization to move forward with
> the revised patch I'm attaching. It's far from ideal, but it's a step.
>
IIRC we already have agreement on removal of xstrerror() globally. Its
not as large as HERE removal and will fix many hidden bugs.
Moving xstrerror() to a debugs-internal mechanism will actually reduce
the size of that change. Which is why I'm continuing with this thread of
discussion at all.
Amos
More information about the squid-dev
mailing list