mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
torture3: Test lock conflict and cleanup
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
2a29c5442d
commit
27eb93c04e
@ -151,6 +151,7 @@ local_tests = [
|
|||||||
"LOCAL-G-LOCK1",
|
"LOCAL-G-LOCK1",
|
||||||
"LOCAL-G-LOCK2",
|
"LOCAL-G-LOCK2",
|
||||||
"LOCAL-G-LOCK3",
|
"LOCAL-G-LOCK3",
|
||||||
|
"LOCAL-G-LOCK4",
|
||||||
"LOCAL-hex_encode_buf",
|
"LOCAL-hex_encode_buf",
|
||||||
"LOCAL-remove_duplicate_addrs2"]
|
"LOCAL-remove_duplicate_addrs2"]
|
||||||
|
|
||||||
|
@ -127,5 +127,6 @@ bool run_pthreadpool_tevent(int dummy);
|
|||||||
bool run_g_lock1(int dummy);
|
bool run_g_lock1(int dummy);
|
||||||
bool run_g_lock2(int dummy);
|
bool run_g_lock2(int dummy);
|
||||||
bool run_g_lock3(int dummy);
|
bool run_g_lock3(int dummy);
|
||||||
|
bool run_g_lock4(int dummy);
|
||||||
|
|
||||||
#endif /* __TORTURE_H__ */
|
#endif /* __TORTURE_H__ */
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "g_lock.h"
|
#include "g_lock.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "lib/util/server_id.h"
|
#include "lib/util/server_id.h"
|
||||||
|
#include "lib/util/sys_rw.h"
|
||||||
|
|
||||||
static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
|
static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
|
||||||
struct tevent_context **ev,
|
struct tevent_context **ev,
|
||||||
@ -311,6 +312,187 @@ bool run_g_lock3(int dummy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
fail:
|
||||||
|
TALLOC_FREE(ctx);
|
||||||
|
TALLOC_FREE(msg);
|
||||||
|
TALLOC_FREE(ev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lock4_child(const char *lockname,
|
||||||
|
int ready_pipe, int exit_pipe)
|
||||||
|
{
|
||||||
|
struct tevent_context *ev = NULL;
|
||||||
|
struct messaging_context *msg = NULL;
|
||||||
|
struct g_lock_ctx *ctx = NULL;
|
||||||
|
NTSTATUS status;
|
||||||
|
ssize_t n;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
|
||||||
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
|
||||||
|
(struct timeval) { .tv_sec = 1 });
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
fprintf(stderr, "child: g_lock_lock returned %s\n",
|
||||||
|
nt_errstr(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = sys_write(ready_pipe, &ok, sizeof(ok));
|
||||||
|
if (n != sizeof(ok)) {
|
||||||
|
fprintf(stderr, "child: write failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
n = sys_read(exit_pipe, &ok, sizeof(ok));
|
||||||
|
if (n != 0) {
|
||||||
|
fprintf(stderr, "child: read failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lock4_done(struct tevent_req *subreq)
|
||||||
|
{
|
||||||
|
int *done = tevent_req_callback_data_void(subreq);
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
status = g_lock_lock_recv(subreq);
|
||||||
|
TALLOC_FREE(subreq);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
fprintf(stderr, "g_lock_lock_recv returned %s\n",
|
||||||
|
nt_errstr(status));
|
||||||
|
*done = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lock4_waited(struct tevent_req *subreq)
|
||||||
|
{
|
||||||
|
int *exit_pipe = tevent_req_callback_data_void(subreq);
|
||||||
|
pid_t child;
|
||||||
|
int status;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
printf("waited\n");
|
||||||
|
|
||||||
|
ok = tevent_wakeup_recv(subreq);
|
||||||
|
TALLOC_FREE(subreq);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "tevent_wakeup_recv failed\n");
|
||||||
|
}
|
||||||
|
close(*exit_pipe);
|
||||||
|
|
||||||
|
child = wait(&status);
|
||||||
|
|
||||||
|
printf("child %d exited with %d\n", (int)child, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test a lock conflict
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool run_g_lock4(int dummy)
|
||||||
|
{
|
||||||
|
struct tevent_context *ev = NULL;
|
||||||
|
struct messaging_context *msg = NULL;
|
||||||
|
struct g_lock_ctx *ctx = NULL;
|
||||||
|
const char *lockname = "lock4";
|
||||||
|
pid_t child;
|
||||||
|
int ready_pipe[2];
|
||||||
|
int exit_pipe[2];
|
||||||
|
NTSTATUS status;
|
||||||
|
bool ret = false;
|
||||||
|
struct tevent_req *req;
|
||||||
|
bool ok;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
|
||||||
|
perror("pipe failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
|
||||||
|
ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
|
||||||
|
if (!ok) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child == -1) {
|
||||||
|
perror("fork failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child == 0) {
|
||||||
|
close(ready_pipe[0]);
|
||||||
|
close(exit_pipe[1]);
|
||||||
|
ok = lock4_child(lockname, ready_pipe[1], exit_pipe[0]);
|
||||||
|
exit(ok ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ready_pipe[1]);
|
||||||
|
close(exit_pipe[0]);
|
||||||
|
|
||||||
|
if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
|
||||||
|
perror("read failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "child returned error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
|
||||||
|
(struct timeval) { .tv_usec = 1 });
|
||||||
|
if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
|
||||||
|
fprintf(stderr, "g_lock_lock returned %s\n",
|
||||||
|
nt_errstr(status));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = g_lock_lock(ctx, lockname, G_LOCK_READ,
|
||||||
|
(struct timeval) { .tv_usec = 1 });
|
||||||
|
if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
|
||||||
|
fprintf(stderr, "g_lock_lock returned %s\n",
|
||||||
|
nt_errstr(status));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
req = g_lock_lock_send(ev, ev, ctx, lockname, G_LOCK_WRITE);
|
||||||
|
if (req == NULL) {
|
||||||
|
fprintf(stderr, "g_lock_lock send failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
tevent_req_set_callback(req, lock4_done, &done);
|
||||||
|
|
||||||
|
req = tevent_wakeup_send(ev, ev, timeval_current_ofs(1, 0));
|
||||||
|
if (req == NULL) {
|
||||||
|
fprintf(stderr, "tevent_wakeup_send failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
tevent_req_set_callback(req, lock4_waited, &exit_pipe[1]);
|
||||||
|
|
||||||
|
done = 0;
|
||||||
|
|
||||||
|
while (done == 0) {
|
||||||
|
int tevent_ret = tevent_loop_once(ev);
|
||||||
|
if (tevent_ret != 0) {
|
||||||
|
perror("tevent_loop_once failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
fail:
|
fail:
|
||||||
TALLOC_FREE(ctx);
|
TALLOC_FREE(ctx);
|
||||||
|
@ -11480,6 +11480,7 @@ static struct {
|
|||||||
{ "LOCAL-G-LOCK1", run_g_lock1, 0 },
|
{ "LOCAL-G-LOCK1", run_g_lock1, 0 },
|
||||||
{ "LOCAL-G-LOCK2", run_g_lock2, 0 },
|
{ "LOCAL-G-LOCK2", run_g_lock2, 0 },
|
||||||
{ "LOCAL-G-LOCK3", run_g_lock3, 0 },
|
{ "LOCAL-G-LOCK3", run_g_lock3, 0 },
|
||||||
|
{ "LOCAL-G-LOCK4", run_g_lock4, 0 },
|
||||||
{ "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
|
{ "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
|
||||||
{ "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
|
{ "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
|
||||||
{NULL, NULL, 0}};
|
{NULL, NULL, 0}};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user