[arch-commits] Commit in udev/trunk (2 files)
Tom Gundersen
tomegun at archlinux.org
Wed Jan 18 11:02:58 UTC 2012
Date: Wednesday, January 18, 2012 @ 06:02:57
Author: tomegun
Revision: 146791
upgpkg: udev 177-3
fix for broken drivers that wait for their firmware in module_init
Added:
udev/trunk/0001-udevd-kill-hanging-event-processes-after-30-seconds.patch
Modified:
udev/trunk/PKGBUILD
----------------------------------------------------------------+
0001-udevd-kill-hanging-event-processes-after-30-seconds.patch | 162 ++++++++++
PKGBUILD | 14
2 files changed, 171 insertions(+), 5 deletions(-)
Added: 0001-udevd-kill-hanging-event-processes-after-30-seconds.patch
===================================================================
--- 0001-udevd-kill-hanging-event-processes-after-30-seconds.patch (rev 0)
+++ 0001-udevd-kill-hanging-event-processes-after-30-seconds.patch 2012-01-18 11:02:57 UTC (rev 146791)
@@ -0,0 +1,162 @@
+From e64fae5573e566ce4fd9b23c68ac8f3096603314 Mon Sep 17 00:00:00 2001
+From: Kay Sievers <kay.sievers at vrfy.org>
+Date: Wed, 18 Jan 2012 05:06:18 +0100
+Subject: [PATCH] udevd: kill hanging event processes after 30 seconds
+
+Some broken kernel drivers load firmware synchronously in the module init
+path and block modprobe until the firmware request is fulfilled.
+
+The modprobe-generated firmware request is a direct child device of the
+device which caused modprobe to run. Child device event are blocked until
+the parent device is handled. This dead-locks until the kernel firmware
+loading timeout of 60 seconds is reached.
+
+The hanging modprobe event should now time-out and allow the firmware
+event to run before the 60 second kernel timeout.
+---
+ src/udev-event.c | 2 +-
+ src/udevd.c | 62 +++++++++++++++++++++++++++++++++++++++++++----------
+ 2 files changed, 51 insertions(+), 13 deletions(-)
+
+diff --git a/src/udev-event.c b/src/udev-event.c
+index 9bdc518..f0b9548 100644
+--- a/src/udev-event.c
++++ b/src/udev-event.c
+@@ -49,7 +49,7 @@ struct udev_event *udev_event_new(struct udev_device *dev)
+ udev_list_init(udev, &event->run_list, false);
+ event->fd_signal = -1;
+ event->birth_usec = now_usec();
+- event->timeout_usec = 60 * 1000 * 1000;
++ event->timeout_usec = 30 * 1000 * 1000;
+ dbg(event->udev, "allocated event %p\n", event);
+ return event;
+ }
+diff --git a/src/udevd.c b/src/udevd.c
+index 11ab19a..77a1e79 100644
+--- a/src/udevd.c
++++ b/src/udevd.c
+@@ -133,6 +133,7 @@ struct worker {
+ struct udev_monitor *monitor;
+ enum worker_state state;
+ struct event *event;
++ unsigned long long event_start_usec;
+ };
+
+ /* passed from worker to main process */
+@@ -372,6 +373,7 @@ out:
+ close(fd_inotify);
+ close(worker_watch[WRITE_END]);
+ udev_rules_unref(rules);
++ udev_builtin_exit(udev);
+ udev_monitor_unref(worker_monitor);
+ udev_unref(udev);
+ udev_log_close();
+@@ -389,6 +391,7 @@ out:
+ worker->monitor = worker_monitor;
+ worker->pid = pid;
+ worker->state = WORKER_RUNNING;
++ worker->event_start_usec = now_usec();
+ worker->event = event;
+ event->state = EVENT_RUNNING;
+ udev_list_node_append(&worker->node, &worker_list);
+@@ -419,6 +422,7 @@ static void event_run(struct event *event)
+ worker_ref(worker);
+ worker->event = event;
+ worker->state = WORKER_RUNNING;
++ worker->event_start_usec = now_usec();
+ event->state = EVENT_RUNNING;
+ return;
+ }
+@@ -610,9 +614,11 @@ static void worker_returned(int fd_worker)
+ continue;
+
+ /* worker returned */
+- worker->event->exitcode = msg.exitcode;
+- event_queue_delete(worker->event, true);
+- worker->event = NULL;
++ if (worker->event) {
++ worker->event->exitcode = msg.exitcode;
++ event_queue_delete(worker->event, true);
++ worker->event = NULL;
++ }
+ if (worker->state != WORKER_KILLED)
+ worker->state = WORKER_IDLE;
+ worker_unref(worker);
+@@ -796,7 +802,7 @@ static void handle_signal(struct udev *udev, int signo)
+ }
+
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+- if (worker->event != NULL) {
++ if (worker->event) {
+ err(udev, "worker [%u] failed while handling '%s'\n",
+ pid, worker->event->devpath);
+ worker->event->exitcode = -32;
+@@ -1574,25 +1580,57 @@ int main(int argc, char *argv[])
+ break;
+
+ /* timeout at exit for workers to finish */
+- timeout = 60 * 1000;
+- } else if (udev_list_node_is_empty(&event_list) && children > 2) {
+- /* set timeout to kill idle workers */
+- timeout = 3 * 1000;
+- } else {
++ timeout = 30 * 1000;
++ } else if (udev_list_node_is_empty(&event_list) && children <= 2) {
++ /* we are idle */
+ timeout = -1;
++ } else {
++ /* kill idle or hanging workers */
++ timeout = 3 * 1000;
+ }
+ fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), timeout);
+ if (fdcount < 0)
+ continue;
+
+ if (fdcount == 0) {
++ struct udev_list_node *loop;
++
++ /* timeout */
+ if (udev_exit) {
+- info(udev, "timeout, giving up waiting for workers to finish\n");
++ err(udev, "timeout, giving up waiting for workers to finish\n");
+ break;
+ }
+
+- /* timeout - kill idle workers */
+- worker_kill(udev, 2);
++ /* kill idle workers */
++ if (udev_list_node_is_empty(&event_list)) {
++ info(udev, "cleanup idle workers\n");
++ worker_kill(udev, 2);
++ }
++
++ /* check for hanging events */
++ udev_list_node_foreach(loop, &worker_list) {
++ struct worker *worker = node_to_worker(loop);
++
++ if (worker->state != WORKER_RUNNING)
++ continue;
++
++ if ((now_usec() - worker->event_start_usec) > 30 * 1000 * 1000) {
++ err(udev, "worker [%u] timeout, kill it\n", worker->pid,
++ worker->event ? worker->event->devpath : "<idle>");
++ kill(worker->pid, SIGKILL);
++ worker->state = WORKER_KILLED;
++ /* drop reference taken for state 'running' */
++ worker_unref(worker);
++ if (worker->event) {
++ err(udev, "seq %llu '%s' killed\n",
++ udev_device_get_seqnum(worker->event->dev), worker->event->devpath);
++ worker->event->exitcode = -64;
++ event_queue_delete(worker->event, true);
++ worker->event = NULL;
++ }
++ }
++ }
++
+ }
+
+ is_worker = is_signal = is_inotify = is_netlink = is_ctrl = false;
+--
+1.7.8.3
+
Modified: PKGBUILD
===================================================================
--- PKGBUILD 2012-01-18 10:53:29 UTC (rev 146790)
+++ PKGBUILD 2012-01-18 11:02:57 UTC (rev 146791)
@@ -7,18 +7,22 @@
pkgbase="udev"
pkgname=('udev' 'udev-compat')
pkgver=177
-pkgrel=1
+pkgrel=3
arch=(i686 x86_64)
url="http://git.kernel.org/?p=linux/hotplug/udev.git;a=summary"
license=('GPL')
groups=('base')
options=(!makeflags !libtool)
makedepends=('gobject-introspection' 'gperf' 'libxslt' 'usbutils' 'kmod')
-source=(ftp://ftp.kernel.org/pub/linux/utils/kernel/hotplug/$pkgbase-$pkgver.tar.xz)
+source=(ftp://ftp.kernel.org/pub/linux/utils/kernel/hotplug/$pkgbase-$pkgver.tar.xz
+ 0001-udevd-kill-hanging-event-processes-after-30-seconds.patch)
build() {
cd $srcdir/$pkgbase-$pkgver
+ # deal with broken drivers waiting for firmware to be loaded
+ patch -p1 -i ../0001-udevd-kill-hanging-event-processes-after-30-seconds.patch
+
./configure --prefix=/usr \
--with-rootprefix= \
--sysconfdir=/etc \
@@ -37,7 +41,7 @@
depends=('util-linux' 'libusb-compat' 'glib2' 'kmod' 'pciutils' 'usbutils' 'pciutils')
install=udev.install
backup=(etc/udev/udev.conf)
-
+
cd $srcdir/$pkgbase-$pkgver
make DESTDIR=${pkgdir} install
@@ -99,5 +103,5 @@
mknod cpu/microcode c 10 184
}
-
-md5sums=('b4e00faf8153fd7202a7ef609284b0c3')
+md5sums=('b4e00faf8153fd7202a7ef609284b0c3'
+ '3e40dca1c4f8194b4633e3befb4da4d4')
More information about the arch-commits
mailing list