Project

General

Profile

Bug #9362 » radosreadtimeout.cpp

Matthias Kiefer, 09/05/2014 05:08 AM

 
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <rados/librados.h>

using namespace std;

/**
* This small program demonstrates the memory corruption of rados_read if a timeout happens
*/

const char *pool = "data";
const char *id = "admin";
const char *confFile = "/etc/ceph/ceph.conf";
int main(int argc, char **argv)
{
// First write the object we will use for demonstrating the memory corruption.
// You can also use any existing object for this problem to be reproduced.
const char* oid = "foo";
string content = "some random string with no special requirement";
rados_t cluster;
rados_ioctx_t ioctx;
rados_create(&cluster, id);
rados_conf_read_file(cluster, confFile);
rados_connect(cluster);
rados_ioctx_create(cluster, pool, &ioctx);
int err = rados_write(ioctx, oid, content.c_str(), content.length(), 0);
printf("result of writing %s: %d\n", oid, err);

rados_ioctx_destroy(ioctx);
rados_shutdown(cluster);
// create a new rados object here, since we have to set the timeout parameter before connect
rados_create(&cluster, id);
rados_conf_read_file(cluster, confFile);
rados_conf_set(cluster, "rados_osd_op_timeout", "0.00001"); // use any small value that will result in a timeout
rados_connect(cluster);
rados_ioctx_create(cluster, pool, &ioctx);

// then we show that the buffer is changed after rados_read returned with a timeout
for(int i=0; i<1000; i++) {
char *buf = new char[content.length()];
err = rados_read(ioctx, oid, buf, content.length(), 0);
printf("result of reading %s: %d\n", oid, err);
if(err == -110) {
int startIndex = 0;
// find the index until which librados already read the object before the timeout occurred
for(int b=0; b<32; b++) {
if(buf[b] == 0) {
startIndex = b;
printf("buffer filled with %d bytes\n", startIndex);
printf("value of byte at index %d: %d\n", startIndex, buf[startIndex]);
break;
}
}
// wait some time to give librados a change to do something
usleep(1000);
// then check if the buffer was changed after the call
if(buf[startIndex] != 0) {
printf("byte at index %d was changed after the call to: %d\n", startIndex, buf[startIndex]);
break;
}
}
else {
printf("no timeout on reading %s. Is rados_osd_op_timeout configured correctly?\n", oid);
}
}
// now try to crash it
for(int i=0; i<5000; i++) {
char *buf = new char[content.length()];
err = rados_read(ioctx, oid, buf, content.length(), 0);
delete[] buf;
printf(".");
fflush(stdout);
usleep(2);
}
rados_ioctx_destroy(ioctx);
rados_shutdown(cluster);
return 0;
}
(1-1/2)