Martin Pitt (pitti) wrote on 2013-08-26:
> I have never actually seen ENOBUFS, or uevents being missed due to it,
> so I think the chance of that is quite small. But I can't assert that
> all messages will be received after an ENOBUFS. But as you said,
> waiting longer in that case is a safer fallback than not waiting at
> all. My hope is that that ENOBUFS situation clears itself up
> automatically after some time, otherwise your whole system would be
> screwed (as you could never receive any uevent).
I think that you can observe ENOBUFS and target uevents being missed due to it
if you try below change. I confirmed using below change that wait-for-root
waits until SIGALRM if wait-for-root failed to receive target uevents. Current
code assumes that socket buffer size is large enough to queue target uevents.
Anyway, although the possibility that wait-for-root waits longer than it should
is remaining, the possibility that wait-for-root waits shorter than it should
was fixed.
udev_monitor_filter_add_match_subsystem_devtype (udev_monitor, "block", NULL);
udev_monitor_enable_receiving (udev_monitor);
@@ -96,11 +104,15 @@ main (int argc,
/* When the device doesn't exist yet, or is still being processed
* by udev, use the monitor socket to wait it to be done.
*/
+ sleep(3); // Inject delay to make socket buffer overflow.
while (1) {
/* even though we use a blocking socket this might still fail
* due to ENOBUFS or similar. */
- while ((udev_device = udev_monitor_receive_device (udev_monitor)) == NULL)
- sleep (1);
+ while (errno = 0, (udev_device = udev_monitor_receive_device (udev_monitor)) == NULL) {
+ const int err = errno;
+ fprintf(stderr, "***** %s (%d)\n", strerror(err), err);
+ //sleep (1);
+ }
if (matching_device (udev_device, devpath)) {
type = udev_device_get_property_value (udev_device, "ID_FS_TYPE");
if (type) {
----------
Martin Pitt (pitti) wrote on 2013-08-26:
> I have never actually seen ENOBUFS, or uevents being missed due to it,
> so I think the chance of that is quite small. But I can't assert that
> all messages will be received after an ENOBUFS. But as you said,
> waiting longer in that case is a safer fallback than not waiting at
> all. My hope is that that ENOBUFS situation clears itself up
> automatically after some time, otherwise your whole system would be
> screwed (as you could never receive any uevent).
I think that you can observe ENOBUFS and target uevents being missed due to it
if you try below change. I confirmed using below change that wait-for-root
waits until SIGALRM if wait-for-root failed to receive target uevents. Current
code assumes that socket buffer size is large enough to queue target uevents.
Anyway, although the possibility that wait-for-root waits longer than it should
is remaining, the possibility that wait-for-root waits shorter than it should
was fixed.
Thank you.
---------- for-root. c for-root. c
--- a/src/wait-
+++ b/src/wait-
@@ -12,6 +12,9 @@
#include <unistd.h>
#include <fcntl.h>
+#include <sys/socket.h>
+#include <libudev.h>
+#include <errno.h>
static int device_queued (struct udev *udev, const char *path); new_from_ netlink (udev, "udev"); udev_monitor_ get_fd( udev_monitor) , SOL_SOCKET, SO_RCVBUF, &buff_size, sizeof(buff_size));
static int matching_device (struct udev_device *device, const char *path);
@@ -60,6 +63,11 @@ main (int argc,
*/
udev = udev_new ();
udev_monitor = udev_monitor_
+ {
+ // Reduce socket buffer size.
+ int buff_size = 4096;
+ setsockopt(
+ }
udev_ monitor_ filter_ add_match_ subsystem_ devtype (udev_monitor, "block", NULL); monitor_ enable_ receiving (udev_monitor); receive_ device (udev_monitor)) == NULL) receive_ device (udev_monitor)) == NULL) { get_property_ value (udev_device, "ID_FS_TYPE");
udev_
@@ -96,11 +104,15 @@ main (int argc,
/* When the device doesn't exist yet, or is still being processed
* by udev, use the monitor socket to wait it to be done.
*/
+ sleep(3); // Inject delay to make socket buffer overflow.
while (1) {
/* even though we use a blocking socket this might still fail
* due to ENOBUFS or similar. */
- while ((udev_device = udev_monitor_
- sleep (1);
+ while (errno = 0, (udev_device = udev_monitor_
+ const int err = errno;
+ fprintf(stderr, "***** %s (%d)\n", strerror(err), err);
+ //sleep (1);
+ }
if (matching_device (udev_device, devpath)) {
type = udev_device_
if (type) {
----------