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();