From bf16decf8d7de356d6bbfda824ac2583d92d2d59 Mon Sep 17 00:00:00 2001 From: Ed Rogalsky Date: Tue, 20 Nov 2012 13:34:18 +0100 Subject: [PATCH] clean thread shutdown implemented in ShuttleThread --- src/jogshuttle.cpp | 70 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/jogshuttle.cpp b/src/jogshuttle.cpp index f9049511..8c9d845f 100644 --- a/src/jogshuttle.cpp +++ b/src/jogshuttle.cpp @@ -85,31 +85,75 @@ bool ShuttleThread::isWorking() void ShuttleThread::run() { kDebug() << "------- STARTING SHUTTLE: " << m_device; - + /* open file descriptor */ const int fd = KDE_open((char *) m_device.toUtf8().data(), O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open Jog Shuttle FILE DESCRIPTOR\n"); - return;; + return; } - EV ev; + EV ev; if (ioctl(fd, EVIOCGRAB, 1) < 0) { fprintf(stderr, "Can't get exclusive access on Jog Shuttle FILE DESCRIPTOR\n"); close(fd); - return;; + return; } + fd_set readset; + struct timeval timeout; + int num_warnings = 0; + int result, iof = -1; + + /* enter thread loop */ while (!stop_me) { - if (read(fd, &ev, sizeof(ev)) < 0) { - if (num_warnings % 10000 == 0) - fprintf(stderr, "Failed to read event from Jog Shuttle FILE DESCRIPTOR (repeated %d times)\n", num_warnings + 1); - num_warnings++; - } - handle_event(ev); + /* reset the read set */ + FD_ZERO(&readset); + FD_SET(fd, &readset); + + /* reinit the timeout structure */ + timeout.tv_sec = 0; + timeout.tv_usec = 300000; /* 300 ms */ + + /* do the select */ + result = select(fd+1, &readset, NULL, NULL, &timeout); + + /* see if there was an error or timeout */ + if (result < 0) { +// perror("select failed"); + } else if (result == 0) { +// puts("TIMEOUT"); + } else { + /* we have input */ + if (FD_ISSET(fd, &readset)) { + /* get fd settings */ + if ((iof = fcntl(fd, F_GETFL, 0)) != -1) { + /* set fd non blocking */ + fcntl(fd, F_SETFL, iof | O_NONBLOCK); + /* read input */ + if (read(fd, &ev, sizeof(ev)) < 0) { + if (num_warnings % 10000 == 0) + /* should not happen cause select called before */ + fprintf(stderr, "Failed to read event from Jog Shuttle FILE DESCRIPTOR (repeated %d times)\n", num_warnings + 1); + num_warnings++; + } + + /* restore settings */ + if (iof != -1) { + fcntl(fd, F_SETFL, iof); + } + /* process event */ + handle_event(ev); + } else { + fprintf(stderr, "Can't set Jog Shuttle FILE DESCRIPTOR to O_NONBLOCK\n"); + stop_me = true; + } + } + } } - close(fd); + /* close the handle and return thread */ + close(fd); } void ShuttleThread::handle_event(EV ev) @@ -226,8 +270,8 @@ void JogShuttle::stopDevice() /* the read fd is in blocking mode => stop_me is broken at the moment */ m_shuttleProcess.stop_me = true; m_shuttleProcess.exit(); - /* give the thread some time to shutdown */ - m_shuttleProcess.wait(100); + /* give the thread some time (ms) to shutdown */ + m_shuttleProcess.wait(600); /* if still running - do it in the hardcore way */ if (m_shuttleProcess.isRunning()) { -- 2.39.2