All of lore.kernel.org
 help / color / mirror / Atom feed
From: Clemens Ladisch <clemens@ladisch.de>
To: Takashi Iwai <tiwai@suse.de>
Cc: alsa-devel@alsa-project.org, Martin Tarenskeen <m.tarenskeen@zonnet.nl>
Subject: [PATCH 2/2] amidi: fix timeout handling
Date: Sun, 10 Apr 2016 21:30:29 +0200	[thread overview]
Message-ID: <570AA9D5.4010708@ladisch.de> (raw)
In-Reply-To: <570AA980.3070802@ladisch.de>

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 <m.tarenskeen@zonnet.nl>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
---
 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 <stdarg.h>
 #include <string.h>
 #include <ctype.h>
+#include <math.h>
 #include <getopt.h>
 #include <errno.h>
 #include <signal.h>
+#include <sys/timerfd.h>
 #include <sys/types.h>
 #include <sys/poll.h>
 #include <sys/stat.h>
@@ -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);

  reply	other threads:[~2016-04-10 19:30 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-10 19:29 [PATCH 1/2] amidi: ignore not only Active Sensing but all System Real-Time messages Clemens Ladisch
2016-04-10 19:30 ` Clemens Ladisch [this message]
2016-04-11  7:00 ` Ricard Wanderlof
2016-04-11 11:17   ` Martin Tarenskeen
2016-04-11 11:47     ` Martin Tarenskeen
2016-04-11 13:29   ` Clemens Ladisch
2016-04-11 13:41     ` Ricard Wanderlof
2016-04-11 14:13       ` Clemens Ladisch
2016-04-11 14:18         ` Ricard Wanderlof
2016-04-17 13:21   ` [PATCH v2 1/2] amidi: ignore not only Active Sensing but also Clock bytes Clemens Ladisch
2016-04-17 13:21     ` [PATCH v2 2/2] amidi: fix timeout handling Clemens Ladisch
2016-08-13 10:27 [PATCH 0/2] amidi: fix handling of ignored messages Clemens Ladisch
2016-08-13 10:29 ` [PATCH 2/2] amidi: fix timeout handling Clemens Ladisch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=570AA9D5.4010708@ladisch.de \
    --to=clemens@ladisch.de \
    --cc=alsa-devel@alsa-project.org \
    --cc=m.tarenskeen@zonnet.nl \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.