[alsa-devel] aplay can't run in background since adding pause support

Takashi Iwai tiwai at suse.de
Tue May 24 07:55:15 CEST 2011


At Mon, 23 May 2011 13:55:44 -0700,
Stephen Warren wrote:
> 
> Jaroslav,
> 
> In recent versions of aplay, if I try to either run them in the
> background, or run them in the foreground, then ^Z and bg them, they
> hang indefinitely:
> 
> aplay foo.wav &
> # doesn't play anything
> 
> aplay foo.wav
> ...
> ^Z
> bg
> [1]+  Stopped      aplay foo.wav
> bg
> [1]+  Stopped      aplay foo.wav
> 
> At least, this is true under ChromeOS on ARM with kernel 2.6.38 and
> ALSA 1.0.24.2, or an Ubuntu Natty rootstock on ARM with the same ChromeOS
> kernel.
> 
> This was introduced by alsa-utils commit:
> 3bd65336222a4d00cefc4db5e74a7a96c07ab567
> aplay/arecord: Added hardware pause support (press SPACE or Enter)
> 
> What happens is that the call to tcsetattr causes the process to receive
> signal TTOU and be stopped. Running under strace yields an infinite loop
> with ioctl(TCSETS) returning -ERESTARTSYS, and being retried.
> 
> I believe this is related to http://lkml.org/lkml/2008/6/2/157.
> 
> I'm not exactly sure how to solve this though. Another post in that
> thread implied that adding a signal handler for TTOU and then adjusting
> the tcsetattr settings might help, but I'm not convinced about that,
> since I believe the -ERESTARTSYS handling loop is inside the call to
> tcsetattr, and hence tcsetattr's parameters can't be changed.
> 
> Does anyone have any ideas? Thanks.

IMO, it's safer to add an option for interactive mode like below.
As aplay has been used since long time ago, we shouldn't introduce
any regression to this basic program.


thanks,

Takashi

---
diff --git a/aplay/aplay.1 b/aplay/aplay.1
index b6caf0b..8cd1d56 100644
--- a/aplay/aplay.1
+++ b/aplay/aplay.1
@@ -137,6 +137,10 @@ by typing aplay.
 Record.  This is the default if the program is invoked
 by typing arecord.
 .TP
+\fI\-i, \-\-interactive\fP
+Allow interactive operation via stdin.
+Currently only pause/resume via space key is implemented.
+.TP
 \fI\-\-disable\-resample\fP
 Disable automatic rate resample.
 .TP
diff --git a/aplay/aplay.c b/aplay/aplay.c
index c09f23c..04959b8 100644
--- a/aplay/aplay.c
+++ b/aplay/aplay.c
@@ -103,6 +103,7 @@ static int avail_min = -1;
 static int start_delay = 0;
 static int stop_delay = 0;
 static int monotonic = 0;
+static int interactive = 0;
 static int can_pause = 0;
 static int verbose = 0;
 static int vumeter = VUMETER_NONE;
@@ -200,6 +201,7 @@ _("Usage: %s [OPTION]... [FILE]...\n"
 "-v, --verbose           show PCM structure and setup (accumulative)\n"
 "-V, --vumeter=TYPE      enable VU meter (TYPE: mono or stereo)\n"
 "-I, --separate-channels one file for each channel\n"
+"-i, --interactive       allow interactive operation from stdin\n"
 "    --disable-resample  disable automatic rate resample\n"
 "    --disable-channels  disable automatic channel conversions\n"
 "    --disable-format    disable automatic format conversions\n"
@@ -404,7 +406,7 @@ enum {
 int main(int argc, char *argv[])
 {
 	int option_index;
-	static const char short_options[] = "hnlLD:qt:c:f:r:d:MNF:A:R:T:B:vV:IPC";
+	static const char short_options[] = "hnlLD:qt:c:f:r:d:MNF:A:R:T:B:vV:IPCi";
 	static const struct option long_options[] = {
 		{"help", 0, 0, 'h'},
 		{"version", 0, 0, OPT_VERSION},
@@ -442,6 +444,7 @@ int main(int argc, char *argv[])
 		{"max-file-time", 1, 0, OPT_MAX_FILE_TIME},
 		{"process-id-file", 1, 0, OPT_PROCESS_ID_FILE},
 		{"use-strftime", 0, 0, OPT_USE_STRFTIME},
+		{"interactive", 0, 0, 'i'},
 		{0, 0, 0, 0}
 	};
 	char *pcm_name = "default";
@@ -608,6 +611,9 @@ int main(int argc, char *argv[])
 			if (file_type == FORMAT_DEFAULT)
 				file_type = FORMAT_WAVE;
 			break;
+		case 'i':
+			interactive = 1;
+			break;
 		case OPT_DISABLE_RESAMPLE:
 			open_mode |= SND_PCM_NO_AUTO_RESAMPLE;
 			break;
@@ -1206,6 +1212,8 @@ static void init_stdin(void)
 	struct termios term;
 	long flags;
 
+	if (!interactive)
+		return;
 	tcgetattr(fileno(stdin), &term);
 	term_c_lflag = term.c_lflag;
 	if (fd == fileno(stdin))
@@ -1221,6 +1229,8 @@ static void done_stdin(void)
 {
 	struct termios term;
 
+	if (!interactive)
+		return;
 	if (fd == fileno(stdin) || term_c_lflag == -1)
 		return;
 	tcgetattr(fileno(stdin), &term);
@@ -1258,6 +1268,8 @@ static void check_stdin(void)
 {
 	unsigned char b;
 
+	if (!interactive)
+		return;
 	if (fd != fileno(stdin)) {
 		while (read(fileno(stdin), &b, 1) == 1) {
 			if (b == ' ' || b == '\r') {


More information about the Alsa-devel mailing list