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 "tap-interface.h"
16 #include <sys/types.h>
19 #include <sys/types.h>
25 static bool am_child
= false;
27 static enum NTDB_ERROR
fork_in_parse(NTDB_DATA key
, NTDB_DATA data
,
28 struct ntdb_context
*ntdb
)
35 /* We expect this to fail. */
36 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != NTDB_ERR_LOCK
)
39 if (ntdb_fetch(ntdb
, key
, &data
) != NTDB_ERR_LOCK
)
42 if (tap_log_messages
!= 2)
48 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
52 int main(int argc
, char *argv
[])
55 struct ntdb_context
*ntdb
;
56 int flags
[] = { NTDB_DEFAULT
, NTDB_NOMMAP
,
57 NTDB_CONVERT
, NTDB_NOMMAP
|NTDB_CONVERT
};
58 NTDB_DATA key
= ntdb_mkdata("key", 3);
59 NTDB_DATA data
= ntdb_mkdata("data", 4);
61 plan_tests(sizeof(flags
) / sizeof(flags
[0]) * 14);
62 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
67 ntdb
= ntdb_open("run-fork-test.ntdb",
68 flags
[i
]|MAYBE_NOSYNC
,
69 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &tap_log_attr
);
73 /* Put a record in here. */
74 ok1(ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) == NTDB_SUCCESS
);
76 ok1(ntdb_chainlock(ntdb
, key
) == NTDB_SUCCESS
);
78 /* We expect this to fail. */
79 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != NTDB_ERR_LOCK
)
82 if (ntdb_fetch(ntdb
, key
, &data
) != NTDB_ERR_LOCK
)
85 if (tap_log_messages
!= 2)
88 /* Child can do this without any complaints. */
89 ntdb_chainunlock(ntdb
, key
);
90 if (tap_log_messages
!= 2)
93 if (tap_log_messages
!= 2)
98 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
99 ntdb_chainunlock(ntdb
, key
);
101 ok1(ntdb_lockall(ntdb
) == NTDB_SUCCESS
);
103 /* We expect this to fail. */
104 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != NTDB_ERR_LOCK
)
107 if (ntdb_fetch(ntdb
, key
, &data
) != NTDB_ERR_LOCK
)
110 if (tap_log_messages
!= 2)
113 /* Child can do this without any complaints. */
114 ntdb_unlockall(ntdb
);
115 if (tap_log_messages
!= 2)
118 if (tap_log_messages
!= 2)
123 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
124 ntdb_unlockall(ntdb
);
126 ok1(ntdb_lockall_read(ntdb
) == NTDB_SUCCESS
);
128 /* We expect this to fail. */
129 /* This would always fail anyway... */
130 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != NTDB_ERR_LOCK
)
133 if (ntdb_fetch(ntdb
, key
, &data
) != NTDB_ERR_LOCK
)
136 if (tap_log_messages
!= 2)
139 /* Child can do this without any complaints. */
140 ntdb_unlockall_read(ntdb
);
141 if (tap_log_messages
!= 2)
144 if (tap_log_messages
!= 2)
149 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
150 ntdb_unlockall_read(ntdb
);
152 ok1(ntdb_transaction_start(ntdb
) == NTDB_SUCCESS
);
153 /* If transactions is empty, noop "commit" succeeds. */
154 ok1(ntdb_delete(ntdb
, key
) == NTDB_SUCCESS
);
156 int last_log_messages
;
158 /* We expect this to fail. */
159 if (ntdb_store(ntdb
, key
, data
, NTDB_REPLACE
) != NTDB_ERR_LOCK
)
162 if (ntdb_fetch(ntdb
, key
, &data
) != NTDB_ERR_LOCK
)
165 if (tap_log_messages
!= 2)
168 if (ntdb_transaction_prepare_commit(ntdb
)
171 if (tap_log_messages
== 2)
174 last_log_messages
= tap_log_messages
;
175 /* Child can do this without any complaints. */
176 ntdb_transaction_cancel(ntdb
);
177 if (tap_log_messages
!= last_log_messages
)
180 if (tap_log_messages
!= last_log_messages
)
185 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
186 ntdb_transaction_cancel(ntdb
);
188 ok1(ntdb_parse_record(ntdb
, key
, fork_in_parse
, ntdb
)
192 /* Child can return from parse without complaints. */
193 if (tap_log_messages
!= 2)
197 ok1(tap_log_messages
== 0);
199 return exit_status();