From patchwork Sun Apr 10 19:30:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Clemens Ladisch X-Patchwork-Id: 8791881 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AFF1CC0553 for ; Sun, 10 Apr 2016 19:31:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BE828201B4 for ; Sun, 10 Apr 2016 19:31:16 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 69B8320173 for ; Sun, 10 Apr 2016 19:31:15 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 81ED9261A03; Sun, 10 Apr 2016 21:31:09 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, RCVD_IN_DNSWL_NONE,UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 279862614A9; Sun, 10 Apr 2016 21:31:01 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 4BE96261507; Sun, 10 Apr 2016 21:31:00 +0200 (CEST) Received: from dehamd003.servertools24.de (dehamd003.servertools24.de [31.47.254.18]) by alsa0.perex.cz (Postfix) with ESMTP id E25F2261469 for ; Sun, 10 Apr 2016 21:30:52 +0200 (CEST) Received: from [192.168.42.181] (tmo-115-5.customers.d1-online.com [80.187.115.5]) by dehamd003.servertools24.de (Postfix) with ESMTPSA id 4D868F52010B; Sun, 10 Apr 2016 21:30:51 +0200 (CEST) To: Takashi Iwai References: <570AA980.3070802@ladisch.de> From: Clemens Ladisch Message-ID: <570AA9D5.4010708@ladisch.de> Date: Sun, 10 Apr 2016 21:30:29 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.1 MIME-Version: 1.0 In-Reply-To: <570AA980.3070802@ladisch.de> X-PPP-Message-ID: <20160410193051.27151.98918@dehamd003.servertools24.de> X-PPP-Vhost: ladisch.de Cc: alsa-devel@alsa-project.org, Martin Tarenskeen Subject: [alsa-devel] [PATCH 2/2] amidi: fix timeout handling X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP The timeout is not supposed to expire when ignored messages are received. This cannot be handled with the poll() timeout, so add a separate timer. Reported-by: Martin Tarenskeen Signed-off-by: Clemens Ladisch --- amidi/amidi.c | 69 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/amidi/amidi.c b/amidi/amidi.c index 4978249..a3515b1 100644 --- a/amidi/amidi.c +++ b/amidi/amidi.c @@ -25,9 +25,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -37,6 +39,8 @@ #include "aconfig.h" #include "version.h" +#define NSEC_PER_SEC 1000000000L + static int do_device_list, do_rawmidi_list; static char *port_name = "default"; static char *send_file_name; @@ -46,7 +50,7 @@ static char *send_data; static int send_data_length; static int receive_file; static int dump; -static int timeout; +static float timeout; static int stop; static snd_rawmidi_t *input, **inputp; static snd_rawmidi_t *output, **outputp; @@ -425,6 +429,7 @@ int main(int argc, char *argv[]) int c, err, ok = 0; int ignore_system_realtime = 1; int do_send_hex = 0; + struct itimerspec itimerspec = { .it_interval = { 0, 0 } }; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { @@ -459,7 +464,7 @@ int main(int argc, char *argv[]) dump = 1; break; case 't': - timeout = atoi(optarg); + timeout = atof(optarg); break; case 'a': ignore_system_realtime = 0; @@ -547,40 +552,64 @@ int main(int argc, char *argv[]) if (inputp) { int read = 0; - int npfds, time = 0; + int npfds; struct pollfd *pfds; - timeout *= 1000; - npfds = snd_rawmidi_poll_descriptors_count(input); + npfds = 1 + snd_rawmidi_poll_descriptors_count(input); pfds = alloca(npfds * sizeof(struct pollfd)); - snd_rawmidi_poll_descriptors(input, pfds, npfds); + + if (timeout > 0) { + pfds[0].fd = timerfd_create(CLOCK_MONOTONIC, 0); + if (pfds[0].fd == -1) { + error("cannot create timer: %s", strerror(errno)); + goto _exit; + } + pfds[0].events = POLLIN; + } else { + pfds[0].fd = -1; + } + + snd_rawmidi_poll_descriptors(input, &pfds[1], npfds - 1); + signal(SIGINT, sig_handler); + + if (timeout > 0) { + float timeout_int; + + itimerspec.it_value.tv_nsec = modff(timeout, &timeout_int) * NSEC_PER_SEC; + itimerspec.it_value.tv_sec = timeout_int; + err = timerfd_settime(pfds[0].fd, 0, &itimerspec, NULL); + if (err < 0) { + error("cannot set timer: %s", strerror(errno)); + goto _exit; + } + } for (;;) { unsigned char buf[256]; int i, length; unsigned short revents; - err = poll(pfds, npfds, 200); + err = poll(pfds, npfds, -1); if (stop || (err < 0 && errno == EINTR)) break; if (err < 0) { error("poll failed: %s", strerror(errno)); break; } - if (err == 0) { - time += 200; - if (timeout && time >= timeout) - break; - continue; - } - if ((err = snd_rawmidi_poll_descriptors_revents(input, pfds, npfds, &revents)) < 0) { + + err = snd_rawmidi_poll_descriptors_revents(input, &pfds[1], npfds - 1, &revents); + if (err < 0) { error("cannot get poll events: %s", snd_strerror(errno)); break; } if (revents & (POLLERR | POLLHUP)) break; - if (!(revents & POLLIN)) + if (!(revents & POLLIN)) { + if (pfds[0].revents & POLLIN) + break; continue; + } + err = snd_rawmidi_read(input, buf, sizeof(buf)); if (err == -EAGAIN) continue; @@ -595,7 +624,7 @@ int main(int argc, char *argv[]) if (length == 0) continue; read += length; - time = 0; + if (receive_file != -1) write(receive_file, buf, length); if (dump) { @@ -603,6 +632,14 @@ int main(int argc, char *argv[]) print_byte(buf[i]); fflush(stdout); } + + if (timeout > 0) { + err = timerfd_settime(pfds[0].fd, 0, &itimerspec, NULL); + if (err < 0) { + error("cannot set timer: %s", strerror(errno)); + break; + } + } } if (isatty(fileno(stdout))) printf("\n%d bytes read\n", read);