1 /* Test forking while holding lock.
3 * There are only five ways to do this currently:
4 * (1) grab a tdb_chainlock, then fork.
5 * (2) grab a tdb_lockall, then fork.
6 * (3) grab a tdb_lockall_read, then fork.
7 * (4) start a transaction, then fork.
8 * (5) fork from inside a tdb_parse() callback.
10 * Note that we don't hold a lock across tdb_traverse callbacks, so
11 * that doesn't matter.
15 #include "tap-interface.h"
16 #include <sys/types.h>
19 #include <sys/types.h>
25 static enum TDB_ERROR fork_in_parse(TDB_DATA key, TDB_DATA data,
26 struct tdb_context *tdb)
31 /* We expect this to fail. */
32 if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
35 if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
38 if (tap_log_messages != 2)
42 if (tap_log_messages != 2)
47 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
51 int main(int argc, char *argv[])
54 struct tdb_context *tdb;
55 int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
56 TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT };
57 struct tdb_data key = tdb_mkdata("key", 3);
58 struct tdb_data data = tdb_mkdata("data", 4);
60 plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
61 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
66 tdb = tdb_open("run-fork-test.tdb", flags[i],
67 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
71 /* Put a record in here. */
72 ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_SUCCESS);
74 ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
76 /* We expect this to fail. */
77 if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
80 if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
83 if (tap_log_messages != 2)
86 tdb_chainunlock(tdb, key);
87 if (tap_log_messages != 3)
90 if (tap_log_messages != 3)
95 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
96 tdb_chainunlock(tdb, key);
98 ok1(tdb_lockall(tdb) == TDB_SUCCESS);
100 /* We expect this to fail. */
101 if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
104 if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
107 if (tap_log_messages != 2)
111 if (tap_log_messages != 2)
114 if (tap_log_messages != 2)
119 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
122 ok1(tdb_lockall_read(tdb) == TDB_SUCCESS);
124 /* We expect this to fail. */
125 /* This would always fail anyway... */
126 if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
129 if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
132 if (tap_log_messages != 2)
135 tdb_unlockall_read(tdb);
136 if (tap_log_messages != 2)
139 if (tap_log_messages != 2)
144 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
145 tdb_unlockall_read(tdb);
147 ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
148 /* If transactions is empty, noop "commit" succeeds. */
149 ok1(tdb_delete(tdb, key) == TDB_SUCCESS);
151 /* We expect this to fail. */
152 if (tdb_store(tdb, key, data, TDB_REPLACE) != TDB_ERR_LOCK)
155 if (tdb_fetch(tdb, key, &data) != TDB_ERR_LOCK)
158 if (tap_log_messages != 2)
161 if (tdb_transaction_commit(tdb) != TDB_ERR_LOCK)
165 if (tap_log_messages < 3)
170 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
171 tdb_transaction_cancel(tdb);
173 ok1(tdb_parse_record(tdb, key, fork_in_parse, tdb)
176 ok1(tap_log_messages == 0);
178 return exit_status();