]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
torture: Test g_lock deadlock detection
authorVolker Lendecke <vl@samba.org>
Wed, 20 Nov 2019 15:03:37 +0000 (16:03 +0100)
committerJeremy Allison <jra@samba.org>
Sat, 23 Nov 2019 01:25:12 +0000 (01:25 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sat Nov 23 01:25:12 UTC 2019 on sn-devel-184

source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_g_lock.c
source3/torture/torture.c

index 44d14feb5d2c4a4419410801ae22b725b7bea2c4..a4851004fa717e6fcb2a51e9f0440997c64ce6ec 100755 (executable)
@@ -222,6 +222,7 @@ local_tests = [
     "LOCAL-G-LOCK4",
     "LOCAL-G-LOCK5",
     "LOCAL-G-LOCK6",
+    "LOCAL-G-LOCK7",
     "LOCAL-NAMEMAP-CACHE1",
     "LOCAL-IDMAP-CACHE1",
     "LOCAL-hex_encode_buf",
index e163e5c3ebfa35f0e4a45162df01ed00ca53fcd8..48c127c30d5c7a08a59c18a285bcf8811de6d823 100644 (file)
@@ -137,6 +137,7 @@ bool run_g_lock3(int dummy);
 bool run_g_lock4(int dummy);
 bool run_g_lock5(int dummy);
 bool run_g_lock6(int dummy);
+bool run_g_lock7(int dummy);
 bool run_g_lock_ping_pong(int dummy);
 bool run_local_namemap_cache1(int dummy);
 bool run_local_idmap_cache1(int dummy);
index 91336352fcc8063fa3124a59496986cb45d899b6..c720e7d661285c1b85ca50674369562f5dc72f4c 100644 (file)
@@ -906,6 +906,171 @@ bool run_g_lock6(int dummy)
        return true;
 }
 
+/*
+ * Test upgrade deadlock
+ */
+
+bool run_g_lock7(int dummy)
+{
+       struct tevent_context *ev = NULL;
+       struct messaging_context *msg = NULL;
+       struct g_lock_ctx *ctx = NULL;
+       const char *lockname = "lock7";
+       TDB_DATA key = string_term_tdb_data(lockname);
+       pid_t child;
+       int ready_pipe[2];
+       int down_pipe[2];
+       ssize_t n;
+       NTSTATUS status;
+       bool ret = false;
+       bool ok = true;
+
+       if ((pipe(ready_pipe) != 0) || (pipe(down_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) {
+               struct tevent_req *req = NULL;
+
+               close(ready_pipe[0]);
+               ready_pipe[0] = -1;
+               close(down_pipe[1]);
+               down_pipe[1] = -1;
+
+               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);
+               }
+
+               printf("%d: locking READ\n", (int)getpid());
+
+               status = g_lock_lock(
+                       ctx,
+                       key,
+                       G_LOCK_READ,
+                       (struct timeval) { .tv_usec = 1 });
+               if (!NT_STATUS_IS_OK(status)) {
+                       fprintf(stderr,
+                               "g_lock_lock(READ) failed: %s\n",
+                               nt_errstr(status));
+                       exit(1);
+               }
+
+               ok = true;
+
+               n = sys_write(ready_pipe[1], &ok, sizeof(ok));
+               if (n != sizeof(ok)) {
+                       fprintf(stderr,
+                               "sys_write failed: %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+
+               n = sys_read(down_pipe[0], &ok, sizeof(ok));
+               if (n != sizeof(ok)) {
+                       fprintf(stderr,
+                               "sys_read failed: %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+
+               printf("%d: starting UPGRADE\n", (int)getpid());
+
+               req = g_lock_lock_send(
+                       msg,
+                       ev,
+                       ctx,
+                       key,
+                       G_LOCK_UPGRADE);
+               if (req == NULL) {
+                       fprintf(stderr, "g_lock_lock_send(UPGRADE) failed\n");
+                       exit(1);
+               }
+
+               n = sys_write(ready_pipe[1], &ok, sizeof(ok));
+               if (n != sizeof(ok)) {
+                       fprintf(stderr,
+                               "sys_write failed: %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+
+               exit(0);
+       }
+
+       close(ready_pipe[1]);
+       close(down_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,
+               key,
+               G_LOCK_READ,
+               (struct timeval) { .tv_usec = 1 });
+       if (!NT_STATUS_IS_OK(status)) {
+               fprintf(stderr,
+                       "g_lock_lock(READ) failed: %s\n",
+                       nt_errstr(status));
+               goto fail;
+       }
+
+       n = sys_write(down_pipe[1], &ok, sizeof(ok));
+       if (n != sizeof(ok)) {
+               fprintf(stderr,
+                       "sys_write failed: %s\n",
+                       strerror(errno));
+               goto fail;
+       }
+
+       if (sys_read(ready_pipe[0], &ok, sizeof(ok)) != sizeof(ok)) {
+               perror("read failed");
+               goto fail;
+       }
+
+       status = g_lock_lock(
+               ctx,
+               key,
+               G_LOCK_UPGRADE,
+               (struct timeval) { .tv_sec = 10 });
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_POSSIBLE_DEADLOCK)) {
+               fprintf(stderr,
+                       "g_lock_lock returned %s\n",
+                       nt_errstr(status));
+               goto fail;
+       }
+
+       ret = true;
+fail:
+       TALLOC_FREE(ctx);
+       TALLOC_FREE(msg);
+       TALLOC_FREE(ev);
+       return ret;
+}
+
 extern int torture_numops;
 extern int torture_nprocs;
 
index 2a66db02c6a38a2eb3a393954d5942018d4f2548..01c6c824342a5ff4c89f6e395beb4b6226891e5f 100644 (file)
@@ -14815,6 +14815,10 @@ static struct {
                .name  = "LOCAL-G-LOCK6",
                .fn    = run_g_lock6,
        },
+       {
+               .name  = "LOCAL-G-LOCK7",
+               .fn    = run_g_lock7,
+       },
        {
                .name  = "LOCAL-G-LOCK-PING-PONG",
                .fn    = run_g_lock_ping_pong,