This repository was archived by the owner on Jun 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 129
Uninitialized data in the TokuDB recovery log
RIch Prohaska edited this page Feb 24, 2014
·
12 revisions
A TokuDB test run with valgrind reported an uninitialized data error when writing a recovery entry into the TokuDB recovery log.
==1032== Syscall param write(buf) points to uninitialised byte(s)
==1032== at 0x3EFA60E4ED: ??? (in /lib64/libpthread-2.12.so)
==1032== by 0xB894038: toku_os_full_write(int, void const*, unsigned long) (file.cc:249)
==1032== by 0xB83248A: write_outbuf_to_logfile(tokulogger*, __toku_lsn*) (logger.cc:513)
==1032== by 0xB83326C: toku_logger_maybe_fsync(tokulogger*, __toku_lsn, int, bool) (logger.cc:836)
==1032== by 0xB8327DE: toku_logger_fsync_if_lsn_not_fsynced(tokulogger*, __toku_lsn) (logger.cc:586)
==1032== by 0xB8493E6: toku_txn_maybe_fsync_log(tokulogger*, __toku_lsn, bool) (txn.cc:600)
==1032== by 0xB7B4EBB: toku_txn_commit(__toku_db_txn*, unsigned int, void (*)(__toku_txn_progress*, void*), void*, bool, bool) (ydb_txn.cc:198)
==1032== by 0xB7B55E9: locked_txn_commit_with_progress(__toku_db_txn*, unsigned int, void (*)(__toku_txn_progress*, void*), void*) (ydb_txn.cc:338)
==1032== by 0xB798B04: commit_txn_with_progress(__toku_db_txn*, unsigned int, THD*) (hatoku_hton.cc:638)
==1032== by 0xB798E82: tokudb_commit(handlerton*, THD*, bool) (hatoku_hton.cc:679)
==1032== by 0x655597: ha_commit_low(THD*, bool, bool) (handler.cc:1496)
==1032== by 0x726681: TC_LOG_MMAP::commit(THD*, bool) (log.cc:2642)
==1032== by 0x6553F0: ha_commit_trans(THD*, bool, bool) (handler.cc:1439)
==1032== by 0x8A825F: trans_commit_stmt(THD*) (transaction.cc:434)
==1032== by 0x7E95E2: mysql_execute_command(THD*) (sql_parse.cc:4997)
TokuDB should not be storing uninitialized data into a fractal tree, so we need to find the the code that neglected to store valid data. An update SQL statement, which uses a read modify write algorithm, was being committed.
Here is an example that only writes the first 4 bits of a byte. Valgrind reports an unitialized data issue.
$ cat setbits.cc
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
static void setbits(unsigned char b[], unsigned nbytes) {
for (unsigned i = 0; i < nbytes; i++) {
for (unsigned j = 0; j < 4; j++) {
if (j & 1)
b[i] |= 1<<j;
else
b[i] &= ~(1<<j);
}
}
}
int main(void) {
unsigned char *b = new unsigned char[1];
setbits(b, 1);
write(1000, b, 1);
delete [] b;
return 0;
}
$ valgrind ./setbits
==26072== Memcheck, a memory error detector
==26072== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==26072== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==26072== Command: ./setbits
==26072==
==26072== Syscall param write(buf) points to uninitialised byte(s)
==26072== at 0x3EF9ADB690: __write_nocancel (in /lib64/libc-2.12.so)
==26072== by 0x4006D8: main (in /extra.home/prohaska/src/setbits/setbits)
==26072== Address 0x4c21040 is 0 bytes inside a block of size 1 alloc'd
==26072== at 0x4A07152: operator new[](unsigned long) (vg_replace_malloc.c:363)
==26072== by 0x4006AD: main (in /extra.home/prohaska/src/setbits/setbits)
==26072==
==26072==
==26072== HEAP SUMMARY:
==26072== in use at exit: 0 bytes in 0 blocks
==26072== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==26072==
==26072== All heap blocks were freed -- no leaks are possible
==26072==
==26072== For counts of detected and suppressed errors, rerun with: -v
==26072== Use --track-origins=yes to see where uninitialised values come from
==26072== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
However, if all of the bits are explicity written, valgrind is silent as it should be.
$ cat setbits.cc
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
static void setbits(unsigned char b[], unsigned nbytes) {
for (unsigned i = 0; i < nbytes; i++) {
for (unsigned j = 0; j < 8; j++) {
if (j & 1)
b[i] |= 1<<j;
else
b[i] &= ~(1<<j);
}
}
}
int main(void) {
unsigned char *b = new unsigned char[1];
setbits(b, 1);
write(1000, b, 1);
delete [] b;
return 0;
}
$ valgrind ./setbits
==26061== Memcheck, a memory error detector
==26061== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==26061== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==26061== Command: ./setbits
==26061==
==26061==
==26061== HEAP SUMMARY:
==26061== in use at exit: 0 bytes in 0 blocks
==26061== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==26061==
==26061== All heap blocks were freed -- no leaks are possible
==26061==
==26061== For counts of detected and suppressed errors, rerun with: -v
==26061== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)