I have been playing with bitcoind, trying to get it working on OpenBSD.
I have stumbled on some bugs that have been fixed.  One included the use
of rand(), which caused all the wallet unit tests to fail.

https://github.com/bitcoin/bitcoin/pull/2312

This also fixed the other BSDs and Windows as well, I believe.

Anyway, they last huge bug I am tracking down is data corruption in my
btree files from db4.  They recommended I try the latest code which
replaces Berekely DB with Google's Leveldb.  I still get corruption.

The good news is, leveldb comes with unit tests.  The corruption_test
fails almost immediately with OpenBSD, but passes on Linux and FreeBSD.

I sifted through the code and created a test to attempt to emulate what
it is doing, which I've included below.  I am not sure if this is the
cause of the corruption, but the output is different on OpenBSD than on
with FreeBSD, Linux, and NetBSD.

On FreeBSD, Linux, and NetBSD, the second fread outputs 43.  On OpenBSD,
it outputs 00.

/*
 * Code
 */
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <err.h>
#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int     do_open(void);
FILE    *do_fopen(void);
void    *do_mmap(int, size_t, off_t);
void    do_munmap(void *, size_t);

const char *fname = "/tmp/mmaptest";

int
do_open(void)
{
        int fd;

        fd = open(fname, O_CREAT | O_RDWR | O_TRUNC, 0644);
        if (fd == -1)
                err(1, "open");

        printf("do_open: %d\n", fd);
        return (fd);
}

FILE *
do_fopen(void)
{
        FILE *fp;

        fp = fopen(fname, "r");
        if (fp == NULL)
                err(1, "fopen");

        printf("do_fopen: %d\n", fileno(fp));   
        return (fp);
}

void *
do_mmap(int fd, size_t len, off_t off)
{
        void *ptr;

        if (ftruncate(fd, off + len) == -1)
                err(1, "ftruncate");
        
        ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off);
        if (ptr == MAP_FAILED)
                err(1, "mmap");

        printf("MMAP %p fd:%d len:%zu offset:%lld\n", ptr, fd, len, off);

        return (ptr);   
}

void
do_munmap(void *ptr, size_t len)
{
        if (munmap(ptr, len) == -1)
                err(1, "munmap");
        printf("UMAP %p len:%zu\n", ptr, len); 
}

int
main(void)
{
        int fd1, fd2;
        char *ptr1, *ptr2;
        FILE *fp;
        char readbuf[32768], writebuf[] = "this is a test";
        size_t bytes;

        fd1 = do_open();
        ptr1 = do_mmap(fd1, 65536, 0);
        memset(ptr1, 'A', 65536);
        do_munmap(ptr1, 65536);

        ptr1 = do_mmap(fd1, 131072, 65536);
        memset(ptr1, 'B', 32768);

        fp = do_fopen();
        bytes = fread(readbuf, 1, sizeof(readbuf), fp);
        printf("fread %zu bytes, readbuf[1024] = %02x\n", bytes, readbuf[1024]);
        fclose(fp);

        fd2 = do_open();
        ptr2 = do_mmap(fd2, 65536, 0);
        memset(ptr2, 'C', 65536);
        do_munmap(ptr2, 65536);

        ptr2 = do_mmap(fd2, 131072, 65536);
        memset(ptr2, 'D', 65536);
        do_munmap(ptr2, 65536);
        close(fd2);

        fp = do_fopen();
        bytes = fread(readbuf, 1, sizeof(readbuf), fp);
        printf("fread %zu bytes, readbuf[1024] = %02x\n", bytes, readbuf[1024]);
        fclose(fp);
        
        fd2 = do_open();
        ptr2 = do_mmap(fd2, 65536, 0);
        memset(ptr2, 'E', 2048);
        do_munmap(ptr2, 65536);

        ptr2 = do_mmap(fd2, 131072, 65536);
        memset(ptr2, 'F', 4096);
        do_munmap(ptr2, 131072);
        
        do_munmap(ptr1, 131072);
        ftruncate(fd1, 100000);
        close(fd1);
 
        return (0);
}

Reply via email to