1 /* Test forking while holding lock.
3 * There are only five ways to do this currently:
4 * (1) grab a ntdb_chainlock, then fork.
5 * (2) grab a ntdb_lockall, then fork.
6 * (3) grab a ntdb_lockall_read, then fork.
7 * (4) start a transaction, then fork.
8 * (5) fork from inside a ntdb_parse() callback.
10 * Note that we don't hold a lock across ntdb_traverse callbacks, so
11 * that doesn't matter.
16 #include "tap-interface.h"
19 static bool am_child = false;
21 static enum NTDB_ERROR fork_in_parse(NTDB_DATA key, NTDB_DATA data,
22 struct ntdb_context *ntdb)
29 /* We expect this to fail. */
30 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
33 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
36 if (tap_log_messages != 2)
42 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
46 int main(int argc, char *argv[])
49 struct ntdb_context *ntdb;
50 int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
51 NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
52 NTDB_DATA key = ntdb_mkdata("key", 3);
53 NTDB_DATA data = ntdb_mkdata("data", 4);
55 plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
56 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
61 ntdb = ntdb_open("run-fork-test.ntdb",
62 flags[i]|MAYBE_NOSYNC,
63 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
67 /* Put a record in here. */
68 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_SUCCESS);
70 ok1(ntdb_chainlock(ntdb, key) == NTDB_SUCCESS);
72 /* We expect this to fail. */
73 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
76 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
79 if (tap_log_messages != 2)
82 /* Child can do this without any complaints. */
83 ntdb_chainunlock(ntdb, key);
84 if (tap_log_messages != 2)
87 if (tap_log_messages != 2)
92 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
93 ntdb_chainunlock(ntdb, key);
95 ok1(ntdb_lockall(ntdb) == NTDB_SUCCESS);
97 /* We expect this to fail. */
98 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
101 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
104 if (tap_log_messages != 2)
107 /* Child can do this without any complaints. */
108 ntdb_unlockall(ntdb);
109 if (tap_log_messages != 2)
112 if (tap_log_messages != 2)
117 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
118 ntdb_unlockall(ntdb);
120 ok1(ntdb_lockall_read(ntdb) == NTDB_SUCCESS);
122 /* We expect this to fail. */
123 /* This would always fail anyway... */
124 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
127 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
130 if (tap_log_messages != 2)
133 /* Child can do this without any complaints. */
134 ntdb_unlockall_read(ntdb);
135 if (tap_log_messages != 2)
138 if (tap_log_messages != 2)
143 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
144 ntdb_unlockall_read(ntdb);
146 ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
147 /* If transactions is empty, noop "commit" succeeds. */
148 ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);
150 int last_log_messages;
152 /* We expect this to fail. */
153 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
156 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
159 if (tap_log_messages != 2)
162 if (ntdb_transaction_prepare_commit(ntdb)
165 if (tap_log_messages == 2)
168 last_log_messages = tap_log_messages;
169 /* Child can do this without any complaints. */
170 ntdb_transaction_cancel(ntdb);
171 if (tap_log_messages != last_log_messages)
174 if (tap_log_messages != last_log_messages)
179 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
180 ntdb_transaction_cancel(ntdb);
182 ok1(ntdb_parse_record(ntdb, key, fork_in_parse, ntdb)
186 /* Child can return from parse without complaints. */
187 if (tap_log_messages != 2)
191 ok1(tap_log_messages == 0);
193 return exit_status();