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.
15 #include "../private.h"
16 #include "tap-interface.h"
18 #include "helpapi-external-agent.h"
20 static bool am_child = false;
22 static enum NTDB_ERROR fork_in_parse(NTDB_DATA key, NTDB_DATA data,
23 struct ntdb_context *ntdb)
30 /* We expect this to fail. */
31 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
34 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
37 if (tap_log_messages != 2)
43 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
47 int main(int argc, char *argv[])
50 struct ntdb_context *ntdb;
51 int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
52 NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
53 NTDB_DATA key = ntdb_mkdata("key", 3);
54 NTDB_DATA data = ntdb_mkdata("data", 4);
56 plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
57 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
62 ntdb = ntdb_open("run-fork-test.ntdb",
63 flags[i]|MAYBE_NOSYNC,
64 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
68 /* Put a record in here. */
69 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_SUCCESS);
71 ok1(ntdb_chainlock(ntdb, key) == NTDB_SUCCESS);
73 /* We expect this to fail. */
74 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
77 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
80 if (tap_log_messages != 2)
83 /* Child can do this without any complaints. */
84 ntdb_chainunlock(ntdb, key);
85 if (tap_log_messages != 2)
88 if (tap_log_messages != 2)
93 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
94 ntdb_chainunlock(ntdb, key);
96 ok1(ntdb_lockall(ntdb) == NTDB_SUCCESS);
98 /* We expect this to fail. */
99 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
102 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
105 if (tap_log_messages != 2)
108 /* Child can do this without any complaints. */
109 ntdb_unlockall(ntdb);
110 if (tap_log_messages != 2)
113 if (tap_log_messages != 2)
118 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
119 ntdb_unlockall(ntdb);
121 ok1(ntdb_lockall_read(ntdb) == NTDB_SUCCESS);
123 /* We expect this to fail. */
124 /* This would always fail anyway... */
125 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
128 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
131 if (tap_log_messages != 2)
134 /* Child can do this without any complaints. */
135 ntdb_unlockall_read(ntdb);
136 if (tap_log_messages != 2)
139 if (tap_log_messages != 2)
144 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
145 ntdb_unlockall_read(ntdb);
147 ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
148 /* If transactions is empty, noop "commit" succeeds. */
149 ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);
151 int last_log_messages;
153 /* We expect this to fail. */
154 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
157 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
160 if (tap_log_messages != 2)
163 if (ntdb_transaction_prepare_commit(ntdb)
166 if (tap_log_messages == 2)
169 last_log_messages = tap_log_messages;
170 /* Child can do this without any complaints. */
171 ntdb_transaction_cancel(ntdb);
172 if (tap_log_messages != last_log_messages)
175 if (tap_log_messages != last_log_messages)
180 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
181 ntdb_transaction_cancel(ntdb);
183 ok1(ntdb_parse_record(ntdb, key, fork_in_parse, ntdb)
187 /* Child can return from parse without complaints. */
188 if (tap_log_messages != 2)
192 ok1(tap_log_messages == 0);
194 return exit_status();