torture3: add LOCAL-G-LOCK6 test
authorStefan Metzmacher <metze@samba.org>
Wed, 20 Dec 2017 08:44:40 +0000 (09:44 +0100)
committerKarolin Seeger <kseeger@samba.org>
Thu, 23 Aug 2018 08:39:30 +0000 (10:39 +0200)
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>
source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_g_lock.c
source3/torture/torture.c

index 696c44b8ba40f36e0ae73b1421c03f7d7d594142..9362627f47d7cf2ba199de2ce3e23a271ef20dd9 100755 (executable)
@@ -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"]
 
index a8400382e1052291877d2de1d336aa9043e108aa..327fa3d6984a60805344425b39490aac8dd90b8e 100644 (file)
@@ -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__ */
index ca373123e118518fb580919efe2b73d9d8527dfb..1134e0d07162de1ca65848231587a5cdd9423405 100644 (file)
@@ -640,5 +640,157 @@ 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;
 }
index f0eb059427f6cb680609266e9696c829c211f755..7c3e8c4a5b03fb4b87aa89977ab087c5e86f1907 100644 (file)
@@ -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}};