static int hash_size = 2;
static int loopnum;
static int count_pipe;
+static bool mutex = false;
static struct tdb_logging_context log_ctx;
#ifdef PRINTF_ATTRIBUTE
static void usage(void)
{
- printf("Usage: tdbtorture [-t] [-k] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
+ printf("Usage: tdbtorture [-t] [-k] [-m] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
exit(0);
}
static void send_count_and_suicide(int sig)
{
+ ssize_t ret;
+
/* This ensures our successor can continue where we left off. */
- write(count_pipe, &loopnum, sizeof(loopnum));
+ do {
+ ret = write(count_pipe, &loopnum, sizeof(loopnum));
+ } while (ret == -1 && errno == EINTR);
/* This gives a unique signature. */
kill(getpid(), SIGUSR2);
}
static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start)
{
- db = tdb_open_ex(filename, hash_size, TDB_DEFAULT,
+ int tdb_flags = TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH;
+
+ if (mutex) {
+ tdb_flags |= TDB_MUTEX_LOCKING;
+ }
+
+ db = tdb_open_ex(filename, hash_size, tdb_flags,
O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
if (!db) {
fatal("db open failed");
log_ctx.log_fn = tdb_log;
- while ((c = getopt(argc, argv, "n:l:s:H:thk")) != -1) {
+ while ((c = getopt(argc, argv, "n:l:s:H:thkm")) != -1) {
switch (c) {
case 'n':
num_procs = strtol(optarg, NULL, 0);
case 'k':
kill_random = 1;
break;
+ case 'm':
+ mutex = tdb_runtime_check_for_robust_mutexes();
+ if (!mutex) {
+ printf("tdb_runtime_check_for_robust_mutexes() returned false\n");
+ exit(1);
+ }
+ break;
default:
usage();
}
seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
}
+ printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
+ num_procs, num_loops, hash_size, seed,
+ (always_transaction ? " (all within transactions)" : ""));
+
if (num_procs == 1 && !kill_random) {
/* Don't fork for this case, makes debugging easier. */
error_count = run_child(test_tdb, 0, seed, num_loops, 0);
}
pids = (pid_t *)calloc(sizeof(pid_t), num_procs);
+ if (pids == NULL) {
+ perror("Unable to allocate memory for pids");
+ exit(1);
+ }
done = (int *)calloc(sizeof(int), num_procs);
+ if (done == NULL) {
+ perror("Unable to allocate memory for done");
+ exit(1);
+ }
if (pipe(pfds) != 0) {
perror("Creating pipe");
for (i=0;i<num_procs;i++) {
if ((pids[i]=fork()) == 0) {
close(pfds[0]);
- if (i == 0) {
- printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
- num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");
- }
exit(run_child(test_tdb, i, seed, num_loops, 0));
}
}
|| WTERMSIG(status) == SIGUSR1) {
/* SIGUSR2 means they wrote to pipe. */
if (WTERMSIG(status) == SIGUSR2) {
- read(pfds[0], &done[j],
- sizeof(done[j]));
+ ssize_t ret;
+
+ do {
+ ret = read(pfds[0], &done[j],
+ sizeof(done[j]));
+ } while (ret == -1 && errno == EINTR);
}
pids[j] = fork();
if (pids[j] == 0)
done:
if (error_count == 0) {
- db = tdb_open_ex(test_tdb, hash_size, TDB_DEFAULT,
+ int tdb_flags = TDB_DEFAULT;
+
+ if (mutex) {
+ tdb_flags |= TDB_NOLOCK;
+ }
+
+ db = tdb_open_ex(test_tdb, hash_size, tdb_flags,
O_RDWR, 0, &log_ctx, NULL);
if (!db) {
fatal("db open failed\n");