linux-v4l2: Add eventfd to signal udev on shutdown
Currently we use signals based on os_event's but the udev code blocks in a 1s select (now poll) that cannot be signalled without an FD. This adds an extra eventfd which will be signalled along with the os_event to trigger the poll. Also switches from select to poll to avoid issues with large fd values.master
parent
bad54448ce
commit
f788e9f6b7
|
@ -15,6 +15,9 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sys/eventfd.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <util/threading.h>
|
||||
|
@ -40,6 +43,7 @@ static pthread_mutex_t udev_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|||
|
||||
static pthread_t udev_thread;
|
||||
static os_event_t *udev_event;
|
||||
static int udev_event_fd;
|
||||
|
||||
static signal_handler_t *udev_signalhandler = NULL;
|
||||
|
||||
|
@ -108,8 +112,6 @@ static void *udev_event_thread(void *vptr)
|
|||
UNUSED_PARAMETER(vptr);
|
||||
|
||||
int fd;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
struct udev *udev;
|
||||
struct udev_monitor *mon;
|
||||
struct udev_device *dev;
|
||||
|
@ -127,12 +129,14 @@ static void *udev_event_thread(void *vptr)
|
|||
fd = udev_monitor_get_fd(mon);
|
||||
|
||||
while (os_event_try(udev_event) == EAGAIN) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
struct pollfd fds[2];
|
||||
|
||||
if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0)
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = udev_event_fd;
|
||||
fds[1].events = POLLIN;
|
||||
|
||||
if (poll(fds, 2, 1000) <= 0)
|
||||
continue;
|
||||
|
||||
dev = udev_monitor_receive_device(mon);
|
||||
|
@ -158,13 +162,19 @@ void v4l2_init_udev(void)
|
|||
if (udev_refs == 0) {
|
||||
if (os_event_init(&udev_event, OS_EVENT_TYPE_MANUAL) != 0)
|
||||
goto fail;
|
||||
if (pthread_create(&udev_thread, NULL, udev_event_thread,
|
||||
NULL) != 0)
|
||||
if ((udev_event_fd = eventfd(0, EFD_CLOEXEC)) < 0)
|
||||
goto fail;
|
||||
if (pthread_create(&udev_thread, NULL, udev_event_thread,
|
||||
NULL) != 0) {
|
||||
close(udev_event_fd);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
udev_signalhandler = signal_handler_create();
|
||||
if (!udev_signalhandler)
|
||||
if (!udev_signalhandler) {
|
||||
close(udev_event_fd);
|
||||
goto fail;
|
||||
}
|
||||
signal_handler_add_array(udev_signalhandler, udev_signals);
|
||||
}
|
||||
udev_refs++;
|
||||
|
@ -180,8 +190,10 @@ void v4l2_unref_udev(void)
|
|||
/* unref udev monitor */
|
||||
if (udev_refs && --udev_refs == 0) {
|
||||
os_event_signal(udev_event);
|
||||
eventfd_write(udev_event_fd, 1);
|
||||
pthread_join(udev_thread, NULL);
|
||||
os_event_destroy(udev_event);
|
||||
close(udev_event_fd);
|
||||
|
||||
if (udev_signalhandler)
|
||||
signal_handler_destroy(udev_signalhandler);
|
||||
|
|
Loading…
Reference in New Issue