I am writing a heavily loaded daemon that should run on FreeBSD 8.0 and on Linux. The main purpose of the daemon is to transfer files requested by their identifier. The identifier is converted to a local file name / file size at the request of db. And then I use sequential calls mmap()to transfer files using send().
However, sometimes there is a mismatch of files in db and file size in the file system (realsize <size in db). In this situation, I sent all the real data blocks and when the next data block is displayed - mmap does not return any errors, just the usual address (I also checked the errno variable, it is zero after mmap). And when the daemon tries to send this block, it gets a Segmentation Fault. (This behavior is guaranteed to be released on FreeBSD 8.0 amd64)
I used safe pre-open validation to ensure size on call stat(). However, real life shows me that segfault can still be raised in rare situations.
So my question is, is there a way to check if a pointer is available before dereferencing? When I opened the kernel in gdb, gdb says that this address is not connected. Perhaps there is another solution that a person can offer.
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define FILENAME "./datafile"
int main()
{
unsigned long i, j;
srand(time(NULL));
unsigned long pagesize = sysconf(_SC_PAGESIZE);
unsigned long basesize = 4 * pagesize;
unsigned long cropsize = 2 * pagesize;
int f = creat(FILENAME, 0644);
for (i = 0; i < basesize; i++) {
unsigned char c = (unsigned char)rand();
if (write(f, &c, 1) < 1) { perror("write"); break; }
}
close(f);
f = open(FILENAME, O_RDONLY);
unsigned char xor = 0;
unsigned long offset = 0;
for (j = 0; j < 4; j++) {
if (j == 2) truncate(FILENAME, cropsize);
char *data = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, f, offset);
if (data == MAP_FAILED) { perror("mmap"); break; }
printf("mmap: %lu@%lu for %i\n", pagesize, offset, f);
for (i = 0; i < pagesize; i++) xor ^= data[i];
offset += pagesize;
}
close(f);
return 0;
}
source
share