[alsa-devel] [PATCH] Fix Jack plugin
I've uploaded a patch to ticket 2727, at https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2727
My background: I'm a software developer, but I know nothing about ALSA development. But I use Jack, and needed to get the Jack plugin working. Since no one has touched the plugin in years, I figured I'd take a stab at fixing it myself.
The symptom: Using the Jack plugin causes whatever program is outputting audio to hang after about 10-20 seconds.
The cause: The plugin creates a pipe, so that the fd's could be polled to indicate completion of a transfer. However, the call to write() blocks when playing audio, as nothing actually reads from the pipe, and it fills up until it blocks.
The solution: This is where my inexperience with ALSA shows up. I don't know the best way to fix it. Making the socket non-blocking fixes the problem, and testing with playback and capture both work properly for me now. However, comparing the code with that of pcm-pulse.c (for piping ALSA output to PulseAudio), it's obvious that the Jack plugin was a hack. It could use more work. However, my fix at least gets me running.
The patch:
--- alsa-plugins-1.0.23/jack/pcm_jack.c 2010-04-16 04:11:10.000000000 -0700 +++ alsa-plugins-1.0.23.new/jack/pcm_jack.c 2011-08-03 21:54:51.795378947 -0700 @@ -307,6 +308,18 @@ return 0; }
+static int make_nonblock(int fd) { + int fl; + + if ((fl = fcntl(fd, F_GETFL)) < 0) + return fl; + + if (fl & O_NONBLOCK) + return 0; + + return fcntl(fd, F_SETFL, fl | O_NONBLOCK); +} + static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name, snd_config_t *playback_conf, snd_config_t *capture_conf, @@ -363,6 +376,9 @@
socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
+ make_nonblock(fd[0]); + make_nonblock(fd[1]); + jack->fd = fd[0];
jack->io.version = SND_PCM_IOPLUG_VERSION;
On 08/04/2011 07:35 AM, Kevin Ross wrote:
I've uploaded a patch to ticket 2727, at https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2727
The symptom: Using the Jack plugin causes whatever program is outputting audio to hang after about 10-20 seconds.
The cause: The plugin creates a pipe, so that the fd's could be polled to indicate completion of a transfer. However, the call to write() blocks when playing audio, as nothing actually reads from the pipe, and it fills up until it blocks.
The patch:
--- alsa-plugins-1.0.23/jack/pcm_jack.c 2010-04-16 04:11:10.000000000 -0700 +++ alsa-plugins-1.0.23.new/jack/pcm_jack.c 2011-08-03 21:54:51.795378947 -0700 @@ -307,6 +308,18 @@ return 0; }
+static int make_nonblock(int fd) {
int fl;
if ((fl = fcntl(fd, F_GETFL)) < 0)
return fl;
if (fl & O_NONBLOCK)
return 0;
return fcntl(fd, F_SETFL, fl | O_NONBLOCK);
+}
- static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name, snd_config_t *playback_conf, snd_config_t *capture_conf,
@@ -363,6 +376,9 @@
socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
make_nonblock(fd[0]);
make_nonblock(fd[1]);
jack->fd = fd[0]; jack->io.version = SND_PCM_IOPLUG_VERSION;
Confirmed to be working. I'm going to send a git patch ASAP.
Cheers
At Thu, 04 Aug 2011 16:11:45 +0200, Adrian Knoth wrote:
On 08/04/2011 07:35 AM, Kevin Ross wrote:
I've uploaded a patch to ticket 2727, at https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2727
The symptom: Using the Jack plugin causes whatever program is outputting audio to hang after about 10-20 seconds.
The cause: The plugin creates a pipe, so that the fd's could be polled to indicate completion of a transfer. However, the call to write() blocks when playing audio, as nothing actually reads from the pipe, and it fills up until it blocks.
The patch:
--- alsa-plugins-1.0.23/jack/pcm_jack.c 2010-04-16 04:11:10.000000000 -0700 +++ alsa-plugins-1.0.23.new/jack/pcm_jack.c 2011-08-03 21:54:51.795378947 -0700 @@ -307,6 +308,18 @@ return 0; }
+static int make_nonblock(int fd) {
int fl;
if ((fl = fcntl(fd, F_GETFL)) < 0)
return fl;
if (fl & O_NONBLOCK)
return 0;
return fcntl(fd, F_SETFL, fl | O_NONBLOCK);
+}
- static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name, snd_config_t *playback_conf, snd_config_t *capture_conf,
@@ -363,6 +376,9 @@
socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
make_nonblock(fd[0]);
make_nonblock(fd[1]);
jack->fd = fd[0]; jack->io.version = SND_PCM_IOPLUG_VERSION;
Confirmed to be working. I'm going to send a git patch ASAP.
OK, it's good to know that it works in multiple systems. I committed the patch now to git tree.
Thanks!
Takashi
As described in issue #2727
https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2727
applications hang after some seconds when using the jack plugin.
Kevin Ross kevin@familyross.net writes:
The cause: The plugin creates a pipe, so that the fd's could be polled to indicate completion of a transfer. However, the call to write() blocks when playing audio, as nothing actually reads from the pipe, and it fills up until it blocks.
Making the socket non-blocking fixes the problem, and testing with playback and capture both work properly for me now.
I've also tested Kevin's patch and confirm it works.
Signed-off-by: Adrian Knoth adi@drcomp.erfurt.thur.de
diff --git a/jack/pcm_jack.c b/jack/pcm_jack.c index 3370a26..a3833c5 100644 --- a/jack/pcm_jack.c +++ b/jack/pcm_jack.c @@ -307,6 +307,18 @@ static int parse_ports(snd_pcm_jack_t *jack, snd_config_t *conf) return 0; }
+static int make_nonblock(int fd) { + int fl; + + if ((fl = fcntl(fd, F_GETFL)) < 0) + return fl; + + if (fl & O_NONBLOCK) + return 0; + + return fcntl(fd, F_SETFL, fl | O_NONBLOCK); +} + static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name, snd_config_t *playback_conf, snd_config_t *capture_conf, @@ -363,6 +375,9 @@ static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name,
socketpair(AF_LOCAL, SOCK_STREAM, 0, fd); + make_nonblock(fd[0]); + make_nonblock(fd[1]); + jack->fd = fd[0];
jack->io.version = SND_PCM_IOPLUG_VERSION;
participants (3)
-
Adrian Knoth
-
Kevin Ross
-
Takashi Iwai