Description of problem: bluetoothd-service-input eats more than 90% cpu since kernel 2997. See Bug 227893 too. Version-Release number of selected component (if applicable): bluez-utils-3.9-1.fc7 How reproducible: Boot the laptop with the 2997 kernel and the bluetooth service enabled Steps to Reproduce: 1. boot laptop with bluetooth hardbutton on laptop turned on 2. wait for boot to finish & login 3. top shows that bluetoothd-service-input eats most of the cpu Actual results: From top: 1579 root 25 0 2708 996 892 R 94.7 0.1 55:14.68 bluetoothd-serv Expected results: bluetoothd-service-input does not use more than 90% of cpu all the time Additional info: strace of the process shows: poll([{fd=4, events=POLLIN}, {fd=7, events=POLLIN, revents=POLLNVAL}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}], 4, -1) = 1
This bug is due to the use of the system GLib and a mistake in not providing the G_IO_HUP, G_IO_ERR and G_IO_NVAL flags to the g_io_add_watch() call. It was working fine with our re-implementation of the GLib mainloop, but with the system GLib it causes problems. Hopefully all of them should be fixed in the CVS.
Applied this fix from upstream to 3.9-2: http://git.infradead.org/?p=bluez-utils.git;a=commitdiff;h=ccb51169867cc60e5141eb52792e239abc6c9f5e
That doesn't help (and I didn't commit it after it failed testing). Current bluez-utils from the git tree is still suffering the same problem.
This stops it eating CPU, although there's still a warning. It's closing the control socket for an incoming connection without ever deregistering it from the glib event loop. diff --git a/input/server.c b/input/server.c index b140bb6..911fc8e 100644 --- a/input/server.c +++ b/input/server.c @@ -69,7 +69,7 @@ static struct session_data *find_session(bdaddr_t *src, bdaddr_t *dst) static gboolean session_event(GIOChannel *chan, GIOCondition cond, gpointer data) { - if (cond & (G_IO_HUP | G_IO_ERR)) + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) return FALSE; return TRUE; @@ -133,7 +133,7 @@ static void create_watch(int sk, struct session_data *session) io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); - g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR, + g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, session_event, session); g_io_channel_unref(io);
Actually if you return FALSE from session_event() it will remove it from the GLib event loop.
Yes, but it still gives me one warning about selecting on an invalid fd. We should remove the fd in question from the glib watch list when we close it at the end of create_device().
That is strange. Please show me the warning that you get.
input[21982]: Bluetooth Input daemon input[21982]: Registered input manager path:/org/bluez/input input[21982]: Created input device: /org/bluez/input/pointing0 input[21982]: Created input device: /org/bluez/input/keyboard1 input[21982]: Incoming connection on PSM 17 input[21982]: Incoming connection on PSM 19 input[21982]: New input device 00:0A:94:C0:7E:17 (CSR HIDEngine Three Button Mouse) (process:21982): GLib-WARNING **: Invalid file descriptor.
I think it happens when glib tries to close the file descriptor after we return FALSE from session_event()... send(3, "<30>Apr 4 10:22:15 input[22013]"..., 103, MSG_NOSIGNAL) = 103 ioctl(9, 0x800448c8, 0x7f9320e4) = 9 ioctl(9, 0x800448c8, 0x7f9320e4) = 0 close(9) = 0 close(8) = 0 close(7) = 0 poll([{fd=4, events=POLLIN}, {fd=7, events=POLLIN, revents=POLLNVAL}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}], 4, -1) = 1 close(7) = -1 EBADF (Bad file descriptor) ... write(2, "\n(process:22013): GLib-WARNING *"..., 61) = 61
This could be caused by g_io_channel_set_close_on_unref() we use. So we better not use it and return FALSE in case of G_IO_NVAL and in case of G_IO_HUP | G_IO_ERR we call g_io_channel_close() in the callback.
*** Bug 231716 has been marked as a duplicate of this bug. ***
I believe this is now fixed.