About
RSS

Programming Pearls: malloc, the Zabbix way


The Zabbix sources define zbx_malloc in include/common.h: line 700 as:


#define zbx_malloc(old, size)   zbx_malloc2(__FILE__, __LINE__, old, size)

zbx_malloc2 is defined in src/libs/zbxcommon/misc.c: line 255 as:


void    *zbx_malloc2(const char *filename, int line, void *old, size_t size)
{
    int max_attempts;
    void    *ptr = NULL;

    /* old pointer must be NULL */
    if (NULL != old)
    {
        zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_malloc: " 	
				"allocating already allocated memory. "
                "Please report this to Zabbix developers.",
                filename, line);
        /* exit if defined DEBUG, ignore otherwise */
        zbx_dbg_assert(0);
    }

    for (
        max_attempts = 10, size = MAX(size, 1);
        0 < max_attempts && NULL == ptr;
        ptr = malloc(size), max_attempts--
    );

    if (NULL != ptr)
        return ptr;

    zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_malloc: out of memory."
		"Requested " ZBX_FS_SIZE_T " bytes.",
            filename, line, (zbx_fs_size_t)size);

    exit(FAIL);
}

So where're the pearls in this?

  1. the old parameter is forced to be NULL, so why pass it at all???

  2. noticed the for loop? It tries to malloc ten times before giving up. This seems to assume that some concurrently running part of zabbix frees memory, or that the system suddenly (while this loop is running, that is) assigns a higher memory bound for zabbix.

  3. noticed the MAX in the for loop? It tries to catch and disguise the error of requesting zero bytes by always returning at least one byte

Fri, 05 Apr 2013
[/osfail] permanent link

MySQL cannot erase data


For eight years it has been known (and Verified) that MySQL does not release diskspace it has claimed in its ibdatax files. The bug leads to full disks and database outages since the only way arround it is to shut down the DB, dump it (consuming even more space) scrubbing the disk and restoring from dump.

This is a veritable showstopper.

Fri, 13 Jan 2012
[/osfail] permanent link

OpenLDAP WTF


Since NIS has seen its hayday (in the early 90ies), we switched to the highly secure LDAP+Kerberos setup. OpenLDAP is touted as the allround “Solution” to all user account management, sorry, I meant to say account provisioning. After converting our NIS passwd file to thousands of LDIF files we imported them with the obvious three-liner

 
  for i in *ldif; do \
	ldapadd -v -W -D "cn=admin,dc=our,dc=domain" \
	    -c -H ldapi:/// -f $i
  done
 
 

After fiddling with half a dozen files in /etc, the client systems could look up user data on the LDAP server. Our test for that was

 
  getent passwd aknownuser
  getent passwd anotherknownuser
 
 
So it seemed plausible to create a list of all users by
	
  getent passwd | awk -F: '{print $1}' > allourusers
	
and install that as a list of valid recipients of e-mails.

This was a grave error, because one of the manymany default settings of OpenLDAP is to return only the first 500 answers to any request. So the list was short by a few hundred accounts.

Considering that LDAP has no concept of a cursor and one cannot ask for the next 500  entries, one can only ask

What the fsck were they thinking???

Mon, 28 Nov 2011
[/osfail] permanent link

Including by explicitly excluding files in Bacula


Bacula's config file format allows the following


FileSet {
	Name = Blah 
	Exclude {
		Options {
			wilddir = /var/tmp*
		}
	}
	File = /var
}

The Directory /var/tmp from the Exclude section is included in the backup, because to exclude it, the proper config would be

FileSet {
	Name = Blah 
	Exclude {
		Options {
			wilddir = /var/tmp*
		}
		exclude = yes
	}
	File = /var
}

Tue, 25 Jan 2011
[/osfail] permanent link