xcalloc called from signal handler

Bernardo Innocenti bernie at codewiz.org
Sun Dec 16 18:53:01 PST 2007



Daniel Stone wrote:
> On Sun, Dec 16, 2007 at 06:48:09PM -0500, Bernardo Innocenti wrote:
>> Matthieu Herrb wrote:
>>> Unfortunalty the xserver 1.4 new Xinput code calls xcalloc() in
>>> functions that are called by the SIGIO handler. This has been identified
>>> as the cause of many X server segfaults on OpenBSD, and will probably
>>> also cause random problems on other systems.
>> I've observed such problems on Linux too, when you try to quit the X server
>> through SIGINT.
> 
> Feel free to file bugs (or, better, send patches) for malloc() on exit
> or in signal handlers.

This is my original post:
  http://lists.freedesktop.org/archives/xorg/2007-March/022406.html

And these are the bugs I filed back then:
  https://bugs.freedesktop.org/show_bug.cgi?id=10212
  https://bugs.freedesktop.org/show_bug.cgi?id=10213


The second one I never got to reproduce because I now have a working
XKB setup...


>> The error message is never going to show up because xcalloc() is
>> supposed to automatically abort() on failure.
> 
> Er, in which parallel universe?
> 
> _X_EXPORT void *
> Xcalloc(unsigned long amount)
> {
>     unsigned long   *ret;
> 
>     ret = Xalloc (amount);
>     if (ret)
>         bzero ((char *) ret, (int) amount);
>     return ret;
> }

Oh, I had assumed Xalloc() had this semantic because this is
what the xfoo() allocators do in GNU projects.

But, the real thing behaves like this:

_X_EXPORT void *
Xalloc(unsigned long amount)
{
    register pointer  ptr;

    if ((long)amount <= 0) {
        return (unsigned long *)NULL;
    }
    /* aligned extra on long word boundary */
    amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
#ifdef MEMBUG
    if (!Must_have_memory && Memory_fail &&
        ((random() % MEM_FAIL_SCALE) < Memory_fail))
        return (unsigned long *)NULL;
#endif
    if ((ptr = (pointer)malloc(amount))) {
        return (unsigned long *)ptr;
    }
    if (Must_have_memory)
        FatalError("Out of memory");
    return (unsigned long *)NULL;
}

... the behavior is actually configurable through the global
variable Must_have_memory, which is usually NULL and gets
flicked to TRUE in specific places, like so:

        Must_have_memory = TRUE; /* XXX */
        spriteTrace = (WindowPtr *)xrealloc(
            spriteTrace, spriteTraceSize*sizeof(WindowPtr));
        Must_have_memory = FALSE; /* XXX */


What a horrible semantics for an allocator!

Would you approve a set of patches that converts our codebase to use
the regular malloc() and free() and kill off this custom allocator?
I'd be delighted to do it.

-- 
 \___/
 |___|   Bernardo Innocenti - http://www.codewiz.org/
  \___\  One Laptop Per Child - http://www.laptop.org/



More information about the xorg mailing list