All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD
@ 2020-03-31 11:19 Michał Winiarski
  2020-03-31 11:27 ` Chris Wilson
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Michał Winiarski @ 2020-03-31 11:19 UTC (permalink / raw)
  To: igt-dev; +Cc: Michał Winiarski, Chris Wilson

From: Michał Winiarski <michal.winiarski@intel.com>

Since timer_delete doesn't give us any guarantees that the thread and
its notify_function isn't currently running, we can hit a use-after-free
in a race condition scenario.
This causes a seemingly random segfault when igt_spin_end from notify
thread is called after igt_spin_free was already called from the main
thread.
Let's fix that by using timerfd and managing the timer thread ourselves.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 lib/igt_dummyload.c | 42 +++++++++++++++++++++++++-----------------
 lib/igt_dummyload.h |  3 ++-
 2 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 657c3c64..694d907d 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -26,6 +26,7 @@
 #include <signal.h>
 #include <pthread.h>
 #include <sys/poll.h>
+#include <sys/timerfd.h>
 
 #include <i915_drm.h>
 
@@ -394,11 +395,20 @@ igt_spin_factory(int fd, const struct igt_spin_factory *opts)
 	return spin;
 }
 
-static void notify(union sigval arg)
+static void *timer_thread(void *data)
 {
-	igt_spin_t *spin = arg.sival_ptr;
+	igt_spin_t *spin = data;
+	struct pollfd pfd;
+	int ret;
 
-	igt_spin_end(spin);
+	pfd.fd = spin->timerfd;
+	pfd.events = POLLIN;
+
+	ret = poll(&pfd, 1, -1);
+	if (ret >= 0)
+		igt_spin_end(spin);
+
+	return NULL;
 }
 
 /**
@@ -412,29 +422,24 @@ static void notify(union sigval arg)
  */
 void igt_spin_set_timeout(igt_spin_t *spin, int64_t ns)
 {
-	timer_t timer;
-	struct sigevent sev;
 	struct itimerspec its;
+	int timerfd;
 
 	igt_assert(ns > 0);
 	if (!spin)
 		return;
 
-	igt_assert(!spin->timer);
+	igt_assert(!spin->timerfd);
+	timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
+	igt_assert(timerfd >= 0);
+	spin->timerfd = timerfd;
 
-	memset(&sev, 0, sizeof(sev));
-	sev.sigev_notify = SIGEV_THREAD;
-	sev.sigev_value.sival_ptr = spin;
-	sev.sigev_notify_function = notify;
-	igt_assert(timer_create(CLOCK_MONOTONIC, &sev, &timer) == 0);
-	igt_assert(timer);
+	pthread_create(&spin->timer_thread, NULL, timer_thread, spin);
 
 	memset(&its, 0, sizeof(its));
 	its.it_value.tv_sec = ns / NSEC_PER_SEC;
 	its.it_value.tv_nsec = ns % NSEC_PER_SEC;
-	igt_assert(timer_settime(timer, 0, &its, NULL) == 0);
-
-	spin->timer = timer;
+	igt_assert(timerfd_settime(timerfd, 0, &its, NULL) == 0);
 }
 
 /**
@@ -484,8 +489,11 @@ void igt_spin_free(int fd, igt_spin_t *spin)
 	igt_list_del(&spin->link);
 	pthread_mutex_unlock(&list_lock);
 
-	if (spin->timer)
-		timer_delete(spin->timer);
+	if (spin->timerfd) {
+		pthread_cancel(spin->timer_thread);
+		igt_assert(pthread_join(spin->timer_thread, NULL) == 0);
+		close(spin->timerfd);
+	}
 
 	igt_spin_end(spin);
 	gem_munmap((void *)((unsigned long)spin->condition & (~4095UL)),
diff --git a/lib/igt_dummyload.h b/lib/igt_dummyload.h
index cb696009..dfba123c 100644
--- a/lib/igt_dummyload.h
+++ b/lib/igt_dummyload.h
@@ -34,7 +34,8 @@
 
 typedef struct igt_spin {
 	unsigned int handle;
-	timer_t timer;
+	int timerfd;
+	pthread_t timer_thread;
 	struct igt_list_head link;
 
 	uint32_t *condition;
-- 
2.26.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD
  2020-03-31 11:19 [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD Michał Winiarski
@ 2020-03-31 11:27 ` Chris Wilson
  2020-03-31 11:41 ` Chris Wilson
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Chris Wilson @ 2020-03-31 11:27 UTC (permalink / raw)
  To: michal, igt-dev; +Cc: michal.winiarski

Quoting Michał Winiarski (2020-03-31 12:19:11)
> From: Michał Winiarski <michal.winiarski@intel.com>
> 
> Since timer_delete doesn't give us any guarantees that the thread and
> its notify_function isn't currently running, we can hit a use-after-free
> in a race condition scenario.
> This causes a seemingly random segfault when igt_spin_end from notify
> thread is called after igt_spin_free was already called from the main
> thread.
> Let's fix that by using timerfd and managing the timer thread ourselves.

Off hand, do you have a feeling on how accurate this method is? I keep
running in situations where the SIGEV_THREAD did not seem reliable and
the spinner never terminated -- so I welcome a chance to do something
different (even if using timerfd + thread is effectively what glibc is
doing behind the scenes, and why I didn't really concern myself with
trying to do better.)
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD
  2020-03-31 11:19 [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD Michał Winiarski
  2020-03-31 11:27 ` Chris Wilson
@ 2020-03-31 11:41 ` Chris Wilson
  2020-03-31 12:43 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Chris Wilson @ 2020-03-31 11:41 UTC (permalink / raw)
  To: michal, igt-dev; +Cc: michal.winiarski

Quoting Michał Winiarski (2020-03-31 12:19:11)
> -static void notify(union sigval arg)
> +static void *timer_thread(void *data)
>  {
> -       igt_spin_t *spin = arg.sival_ptr;
> +       igt_spin_t *spin = data;
> +       struct pollfd pfd;
> +       int ret;
>  
> -       igt_spin_end(spin);
> +       pfd.fd = spin->timerfd;
> +       pfd.events = POLLIN;
> +
> +       ret = poll(&pfd, 1, -1);
> +       if (ret >= 0)
> +               igt_spin_end(spin);

uint64_t count;

if (read(spin->timer_fd, &count, sizeof(count)) > 0)
	igt_spin_end(spin);

would suffice. Not sure of the comparative latency.

However, that would allow us to close(spin->timerfd) first in
cancellation, would should report -ECANCELLED quickest.

So overall, I'm left with the worry of a thread per timeout. Though we
do typically only use one spinner timeout at a time, so it's merely the
overhead of creating a thread which should not be significant.

Ok, so just the question of poll() vs read() [and corresponding cleanup
order] and we're good.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [igt-dev] ✗ Fi.CI.BAT: failure for lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD
  2020-03-31 11:19 [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD Michał Winiarski
  2020-03-31 11:27 ` Chris Wilson
  2020-03-31 11:41 ` Chris Wilson
@ 2020-03-31 12:43 ` Patchwork
  2020-03-31 13:52 ` [igt-dev] [PATCH] " Chris Wilson
  2020-04-01  2:41 ` [igt-dev] ✗ Fi.CI.BAT: failure for lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD (rev2) Patchwork
  4 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2020-03-31 12:43 UTC (permalink / raw)
  To: Michał Winiarski; +Cc: igt-dev

== Series Details ==

Series: lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD
URL   : https://patchwork.freedesktop.org/series/75309/
State : failure

== Summary ==

CI Bug Log - changes from IGT_5548 -> IGTPW_4380
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_4380 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_4380, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_4380/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_4380:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live@execlists:
    - fi-icl-y:           [PASS][1] -> [INCOMPLETE][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5548/fi-icl-y/igt@i915_selftest@live@execlists.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_4380/fi-icl-y/igt@i915_selftest@live@execlists.html

  
Known issues
------------

  Here are the changes found in IGTPW_4380 that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@i915_selftest@live@execlists:
    - fi-kbl-7500u:       [INCOMPLETE][3] ([CI#80] / [i915#656]) -> [PASS][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5548/fi-kbl-7500u/igt@i915_selftest@live@execlists.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_4380/fi-kbl-7500u/igt@i915_selftest@live@execlists.html

  
  [CI#80]: https://gitlab.freedesktop.org/gfx-ci/i915-infra/issues/80
  [i915#656]: https://gitlab.freedesktop.org/drm/intel/issues/656


Participating hosts (47 -> 43)
------------------------------

  Additional (1): fi-bsw-n3050 
  Missing    (5): fi-hsw-4200u fi-skl-6770hq fi-bsw-cyan fi-ctg-p8600 fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5548 -> IGTPW_4380

  CI-20190529: 20190529
  CI_DRM_8222: 6970d295e51e3b03d7ee3f781522398402d3a35d @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_4380: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_4380/index.html
  IGT_5548: d9e70dc1b35633b7d5c81cbfa165e331189eb260 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_4380/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD
  2020-03-31 11:19 [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD Michał Winiarski
                   ` (2 preceding siblings ...)
  2020-03-31 12:43 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
@ 2020-03-31 13:52 ` Chris Wilson
  2020-04-01  2:41 ` [igt-dev] ✗ Fi.CI.BAT: failure for lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD (rev2) Patchwork
  4 siblings, 0 replies; 6+ messages in thread
From: Chris Wilson @ 2020-03-31 13:52 UTC (permalink / raw)
  To: michal, igt-dev; +Cc: michal.winiarski

Quoting Michał Winiarski (2020-03-31 12:19:11)
> From: Michał Winiarski <michal.winiarski@intel.com>
> 
> Since timer_delete doesn't give us any guarantees that the thread and
> its notify_function isn't currently running, we can hit a use-after-free
> in a race condition scenario.
> This causes a seemingly random segfault when igt_spin_end from notify
> thread is called after igt_spin_free was already called from the main
> thread.
> Let's fix that by using timerfd and managing the timer thread ourselves.
> 
> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>

Seems I was confused with the meaning of timerfd_canceled() and imbued
it with properties it did not have,
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [igt-dev] ✗ Fi.CI.BAT: failure for lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD (rev2)
  2020-03-31 11:19 [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD Michał Winiarski
                   ` (3 preceding siblings ...)
  2020-03-31 13:52 ` [igt-dev] [PATCH] " Chris Wilson
@ 2020-04-01  2:41 ` Patchwork
  4 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2020-04-01  2:41 UTC (permalink / raw)
  To: Michał Winiarski; +Cc: igt-dev

== Series Details ==

Series: lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD (rev2)
URL   : https://patchwork.freedesktop.org/series/75309/
State : failure

== Summary ==

Series 75309 revision 2 was fully merged or fully failed: no git log

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-04-01  2:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-31 11:19 [igt-dev] [PATCH] lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD Michał Winiarski
2020-03-31 11:27 ` Chris Wilson
2020-03-31 11:41 ` Chris Wilson
2020-03-31 12:43 ` [igt-dev] ✗ Fi.CI.BAT: failure for " Patchwork
2020-03-31 13:52 ` [igt-dev] [PATCH] " Chris Wilson
2020-04-01  2:41 ` [igt-dev] ✗ Fi.CI.BAT: failure for lib/igt_dummyload: Use timerfd rather than SIGEV_THREAD (rev2) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.