diff options
author | Stefan Metzmacher <metze@samba.org> | 2017-12-20 09:44:40 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2018-08-23 10:39:30 +0200 |
commit | 72a417741bf90b1a20e4d28cf720d43a3a358d03 (patch) | |
tree | a1eb987d24263b696381273ccd49d9b7d2bf65f9 /source3/torture | |
parent | 50b081a609e03cd6cfda89ffb78c14ba1cbccdbc (diff) | |
download | samba-72a417741bf90b1a20e4d28cf720d43a3a358d03.tar.gz |
torture3: add LOCAL-G-LOCK6 test
This is a regression test for bug #13195.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13195
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Diffstat (limited to 'source3/torture')
-rw-r--r-- | source3/torture/proto.h | 1 | ||||
-rw-r--r-- | source3/torture/test_g_lock.c | 152 | ||||
-rw-r--r-- | source3/torture/torture.c | 1 |
3 files changed, 154 insertions, 0 deletions
diff --git a/source3/torture/proto.h b/source3/torture/proto.h index a8400382e10..327fa3d6984 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -132,5 +132,6 @@ bool run_g_lock2(int dummy); bool run_g_lock3(int dummy); bool run_g_lock4(int dummy); bool run_g_lock5(int dummy); +bool run_g_lock6(int dummy); #endif /* __TORTURE_H__ */ diff --git a/source3/torture/test_g_lock.c b/source3/torture/test_g_lock.c index ca373123e11..1134e0d0716 100644 --- a/source3/torture/test_g_lock.c +++ b/source3/torture/test_g_lock.c @@ -642,3 +642,155 @@ bool run_g_lock5(int dummy) return true; } + +struct lock6_parser_state { + size_t num_locks; +}; + +static void lock6_parser(const struct g_lock_rec *locks, + size_t num_locks, + const uint8_t *data, + size_t datalen, + void *private_data) +{ + struct lock6_parser_state *state = private_data; + state->num_locks = num_locks; +} + +/* + * Test cleanup with contention and stale locks + */ + +bool run_g_lock6(int dummy) +{ + struct tevent_context *ev = NULL; + struct messaging_context *msg = NULL; + struct g_lock_ctx *ctx = NULL; + const char *lockname = "lock6"; + pid_t child; + int exit_pipe[2], ready_pipe[2]; + NTSTATUS status; + size_t i, nprocs; + int ret; + bool ok; + ssize_t nread; + char c; + + if ((pipe(exit_pipe) != 0) || (pipe(ready_pipe) != 0)) { + perror("pipe failed"); + return false; + } + + ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx); + if (!ok) { + fprintf(stderr, "get_g_lock_ctx failed"); + return false; + } + + nprocs = 2; + for (i=0; i<nprocs; i++) { + + child = fork(); + + if (child == -1) { + perror("fork failed"); + return false; + } + + if (child == 0) { + TALLOC_FREE(ctx); + + status = reinit_after_fork(msg, ev, false, ""); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, "reinit_after_fork failed: %s\n", + nt_errstr(status)); + exit(1); + } + + close(ready_pipe[0]); + close(exit_pipe[1]); + + ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx); + if (!ok) { + fprintf(stderr, "get_g_lock_ctx failed"); + exit(1); + } + status = g_lock_lock(ctx, lockname, G_LOCK_READ, + (struct timeval) { .tv_sec = 1 }); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "child g_lock_lock failed %s\n", + nt_errstr(status)); + exit(1); + } + if (i == 0) { + exit(0); + } + close(ready_pipe[1]); + nread = sys_read(exit_pipe[0], &c, sizeof(c)); + if (nread != 0) { + fprintf(stderr, "sys_read returned %zu (%s)\n", + nread, strerror(errno)); + exit(1); + } + exit(0); + } + } + + close(ready_pipe[1]); + + nread = sys_read(ready_pipe[0], &c, sizeof(c)); + if (nread != 0) { + fprintf(stderr, "sys_read returned %zd (%s)\n", + nread, strerror(errno)); + return false; + } + + { + int child_status; + ret = waitpid(-1, &child_status, 0); + if (ret == -1) { + perror("waitpid failed"); + return false; + } + } + + { + struct lock6_parser_state state; + + status = g_lock_dump(ctx, lockname, lock6_parser, &state); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, "g_lock_dump returned %s\n", + nt_errstr(status)); + return false; + } + + if (state.num_locks != nprocs) { + fprintf(stderr, "nlocks=%zu, expected %zu\n", + state.num_locks, nprocs); + return false; + } + + status = g_lock_lock(ctx, lockname, G_LOCK_WRITE, + (struct timeval) { .tv_sec = 1 }); + if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + fprintf(stderr, "g_lock_lock should have failed with %s - %s\n", + nt_errstr(NT_STATUS_IO_TIMEOUT), + nt_errstr(status)); + return false; + } + } + + close(exit_pipe[1]); + + { + int child_status; + ret = waitpid(-1, &child_status, 0); + if (ret == -1) { + perror("waitpid failed"); + return false; + } + } + + return true; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index f0eb059427f..7c3e8c4a5b0 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -11848,6 +11848,7 @@ static struct { { "LOCAL-G-LOCK3", run_g_lock3, 0 }, { "LOCAL-G-LOCK4", run_g_lock4, 0 }, { "LOCAL-G-LOCK5", run_g_lock5, 0 }, + { "LOCAL-G-LOCK6", run_g_lock6, 0 }, { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 }, { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 }, {NULL, NULL, 0}}; |