diff options
Diffstat (limited to 'source3')
-rwxr-xr-x | source3/selftest/tests.py | 1 | ||||
-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 |
4 files changed, 155 insertions, 0 deletions
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 696c44b8ba4..9362627f47d 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -161,6 +161,7 @@ local_tests = [ "LOCAL-G-LOCK3", "LOCAL-G-LOCK4", "LOCAL-G-LOCK5", + "LOCAL-G-LOCK6", "LOCAL-hex_encode_buf", "LOCAL-remove_duplicate_addrs2"] 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}}; |