From 592d71ff76318b6389f6866d5394a844c7e35513 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 8 Dec 2010 17:04:59 -0600 Subject: [PATCH] core: work around udev parallel startup race Ignore devices that aren't completely configured by udev yet. If ModemManager is started in parallel with udev, explicitly requesting devices may return devices for which not all udev rules have yet been applied (a bug in udev/gudev). Since we often need those rules to match the device to a specific ModemManager driver, we need to ensure that all rules have been processed before handling a device. Do this by adding an item to the environment of each device that MM might possibly be interested in, and ignoring devices that don't have that. When the device is fully processed by udev, MM will get an 'add' event and the device will have all rules applied. --- src/80-mm-candidate.rules | 16 ++++++++++++++++ src/Makefile.am | 3 ++- src/mm-manager.c | 13 ++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/80-mm-candidate.rules diff --git a/src/80-mm-candidate.rules b/src/80-mm-candidate.rules new file mode 100644 index 00000000..f396cfcf --- /dev/null +++ b/src/80-mm-candidate.rules @@ -0,0 +1,16 @@ +# do not edit this file, it will be overwritten on update + +# Tag any devices that MM might be interested in; if ModemManager is started +# up right after udev, when MM explicitly requests devices on startup it may +# get devices that haven't had all rules run yet. Thus, we tag devices we're +# interested in and when handling devices during MM startup we ignore any +# that don't have this tag. MM will still get the udev 'add' event for the +# device a short while later and then process it as normal. + +ACTION!="add|change", GOTO="mm_candidate_end" + +SUBSYSTEM=="tty", ENV{ID_MM_CANDIDATE}="1" +SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1" + +LABEL="mm_candidate_end" + diff --git a/src/Makefile.am b/src/Makefile.am index cadc98ac..de15beea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,8 @@ udevrulesdir = $(UDEV_BASE_DIR)/rules.d udevrules_DATA = \ 77-mm-usb-device-blacklist.rules \ 77-mm-pcmcia-device-blacklist.rules \ - 77-mm-platform-serial-whitelist.rules + 77-mm-platform-serial-whitelist.rules \ + 80-mm-candidate.rules EXTRA_DIST = \ $(udevrules_DATA) diff --git a/src/mm-manager.c b/src/mm-manager.c index 0aaac9cf..605ec5a1 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -733,7 +733,7 @@ device_added (MMManager *manager, GUdevDevice *device) const char *subsys, *name, *physdev_path, *physdev_subsys; SupportsInfo *info; char *key; - gboolean found; + gboolean found, is_candidate; GUdevDevice *physdev = NULL; MMPlugin *plugin; MMModem *existing; @@ -750,6 +750,17 @@ device_added (MMManager *manager, GUdevDevice *device) if (strncmp (name, "tty", 3) == 0 && isdigit (name[3])) return; + /* Ignore devices that aren't completely configured by udev yet. If + * ModemManager is started in parallel with udev, explicitly requesting + * devices may return devices for which not all udev rules have yet been + * applied (a bug in udev/gudev). Since we often need those rules to match + * the device to a specific ModemManager driver, we need to ensure that all + * rules have been processed before handling a device. + */ + is_candidate = g_udev_device_get_property_as_boolean (device, "ID_MM_CANDIDATE"); + if (!is_candidate) + return; + if (find_modem_for_port (manager, subsys, name)) return;