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
)
28 int status
, extra_messages
;
30 if (tdb_get_flags(tdb
) & TDB_VERSION1
) {
37 /* We expect this to fail. */
38 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) != TDB_ERR_LOCK
)
40 tap_log_messages
-= extra_messages
;
42 if (tdb_fetch(tdb
, key
, &data
) != TDB_ERR_LOCK
)
45 tap_log_messages
-= extra_messages
;
46 if (tap_log_messages
!= 2)
50 if (tap_log_messages
!= 2)
55 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
59 int main(int argc
, char *argv
[])
62 struct tdb_context
*tdb
;
63 int flags
[] = { TDB_DEFAULT
, TDB_NOMMAP
,
64 TDB_CONVERT
, TDB_NOMMAP
|TDB_CONVERT
,
65 TDB_VERSION1
, TDB_NOMMAP
|TDB_VERSION1
,
66 TDB_CONVERT
|TDB_VERSION1
,
67 TDB_NOMMAP
|TDB_CONVERT
|TDB_VERSION1
};
68 struct tdb_data key
= tdb_mkdata("key", 3);
69 struct tdb_data data
= tdb_mkdata("data", 4);
71 plan_tests(sizeof(flags
) / sizeof(flags
[0]) * 14);
72 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
73 int status
, extra_messages
;
75 if (flags
[i
] & TDB_VERSION1
) {
83 tdb
= tdb_open("run-fork-test.tdb", flags
[i
],
84 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &tap_log_attr
);
88 /* Put a record in here. */
89 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_SUCCESS
);
91 ok1(tdb_chainlock(tdb
, key
) == TDB_SUCCESS
);
93 /* We expect this to fail. */
94 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) != TDB_ERR_LOCK
)
96 tap_log_messages
-= extra_messages
;
98 if (tdb_fetch(tdb
, key
, &data
) != TDB_ERR_LOCK
)
100 tap_log_messages
-= extra_messages
;
102 if (tap_log_messages
!= 2)
105 tdb_chainunlock(tdb
, key
);
106 if (tap_log_messages
!= 3)
109 if (tap_log_messages
!= 3)
114 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
115 tdb_chainunlock(tdb
, key
);
117 ok1(tdb_lockall(tdb
) == TDB_SUCCESS
);
119 /* We expect this to fail. */
120 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) != TDB_ERR_LOCK
)
122 tap_log_messages
-= extra_messages
;
124 if (tdb_fetch(tdb
, key
, &data
) != TDB_ERR_LOCK
)
126 tap_log_messages
-= extra_messages
;
128 if (tap_log_messages
!= 2)
132 if (tap_log_messages
!= 2)
135 if (tap_log_messages
!= 2)
140 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
143 ok1(tdb_lockall_read(tdb
) == TDB_SUCCESS
);
145 /* We expect this to fail. */
146 /* This would always fail anyway... */
147 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) != TDB_ERR_LOCK
)
149 tap_log_messages
-= extra_messages
;
151 if (tdb_fetch(tdb
, key
, &data
) != TDB_ERR_LOCK
)
153 tap_log_messages
-= extra_messages
;
155 if (tap_log_messages
!= 2)
158 tdb_unlockall_read(tdb
);
159 if (tap_log_messages
!= 2)
162 if (tap_log_messages
!= 2)
167 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
168 tdb_unlockall_read(tdb
);
170 ok1(tdb_transaction_start(tdb
) == TDB_SUCCESS
);
171 /* If transactions is empty, noop "commit" succeeds. */
172 ok1(tdb_delete(tdb
, key
) == TDB_SUCCESS
);
174 /* We expect this to fail. */
175 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) != TDB_ERR_LOCK
)
177 tap_log_messages
-= extra_messages
;
179 if (tdb_fetch(tdb
, key
, &data
) != TDB_ERR_LOCK
)
181 tap_log_messages
-= extra_messages
;
183 if (tap_log_messages
!= 2)
186 if (tdb_transaction_commit(tdb
) != TDB_ERR_LOCK
)
188 tap_log_messages
-= extra_messages
;
191 if (tap_log_messages
< 3)
196 ok1(WIFEXITED(status
) && WEXITSTATUS(status
) == 0);
197 tdb_transaction_cancel(tdb
);
199 ok1(tdb_parse_record(tdb
, key
, fork_in_parse
, tdb
)
202 ok1(tap_log_messages
== 0);
204 return exit_status();