#787781 gnupg-agent: broken pipe error when a program using agent is invoked by stdbuf -oL

#787781#5
Date:
2015-06-04 23:04:53 UTC
From:
To:
Hi,
i have a script that uses pass [0] password manager, which on his hand
uses gpg-agent to remember the master passphrase, as you can see.
Also i have to filter its output, so i pipe it into another script,
but since i want the output to be unbuffered to get a more real-time
feedback, i tried calling it this way:

stdbuf -oL pass <pass_arguments>

which buffers on a per line basis. On my x86 pc everything is fine,
while on my arm device i get:

gpg: error writing to `-': Broken pipe
gpg: handle plaintext failed: Broken pipe

but after that the script works as expected.
So i was wondering if any tool using gpg-agent invoked with stdbuf
with '-oL' option gives this error. I tried using '-o0' instead of
'-oL' as stdbuf option, and this gives no problems. I also tried
doing some symmetric encryptions/decriptions (not involving gpg-agent)
to make sure the issue was on the agent side, invoking every time gpg
with stdbuf, and indeed no error is showed when the agent is not used.


P.S.:
I really didn't know if this issue had the requisites to be reported
as bug, so forgive me in case it's not, or let me know if more details
are needed.


[0] http://www.passwordstore.org

#787781#10
Date:
2015-06-05 00:29:11 UTC
From:
To:
Control: affects 787781 + pass
Control: tags + help moreinfo

Is that the only difference between your arm device and your x86 device?

From the footer in your bug report, you're using pinentry-curses on the
arm device.  is this true for x86 as well, or are you using a different
pinentry there?

on each machine, what do these show?

  readlink -f /etc/alternatives/pinentry
  grep pinentry ~/.gnupg/*.conf

I think the issue might be related to the choice of pinentry on the
different platforms, but i'm not sure.  Maybe the pass developers can
shed some light on the subject?

#787781#19
Date:
2015-06-05 09:49:27 UTC
From:
To:
Hi, thanks.
Well, after some quick tests the results push me to explain the whole
script, which i didn't do at the beginning to just keep to focus on the
issue itself without additional bloat, because in any case the error
is on the gpg functionality which is used by pass only. So everything
i wrote (with some corrections i'll write now) is also reproducible
without knowing the full details of my scripts, but we never know they
may be useful...

The script actually calls mpop pop3 client, which i set to use its
passwordeval functionality to retrieve appropriate passwords for each
account from pass password manager.
mpop is invoked via stdbuf (to achieve line by line printing) piping
its output into another script. So it may be logically represented
something like:
mpop (=> pass (=> gpg + gpg-agent)) | anotherscript
while the actual command in the script is:

stdbuf -oL mpop <mpop_arguments> | anotherscript

The second part after the pipe should be not relevant at all, since
the issue also happens without any piping.

The reason i decided to describe the full structure is that in the
mpoprc config file, pass is called just with the account i want the
password for as argument, such as:

passwordeval "pass <my_mail_account>"

And this results in the broken pipe error as reported.
Anyways i'm not able to get a broken pipe directly calling on a
terminal:

stdbuf -oL pass <my_mail_account>

which whould be equivalent, unless i also use the -c switch (that
copies the output to clipboard instead of the stdout). So:

stdbuf -oL pass -c <pass_arguments>

gives broken pipe.
This was the command i was using to test yesterday from the command
line, but i tought the -c switch was not relevant so in the quoted
command in my first mail i didn't specify it.
I decided to describe everything because these last steps seemed weird
to me.

So to sum up, the broken pipe error is present when mpop calls pass
with just the mail account as argument, or on the command line
specifying the -c switch too (always invoking them via stdbuf).

Another weird thing i noticed is that if i call consecutively multiple
times the command line command (the one with -c) discussed above, the
error happens one time but not the following, then it shows again and
so on alternating almost deterministically, but sometimes it doesn't
alternate.

Yes, this should be the only difference, i keep the two machines
synced on most scripts and using the same packages (they are both
debian testing too). The kernel is different anyways, it's 3.8.11 on
th arm side, if that matters.

I use pinentry on both. The readlink command shows
"/usr/bin/pinentry-curses" while grep finds nothing, on both machines.

#787781#24
Date:
2015-06-05 23:52:32 UTC
From:
To:
A quick update, just for information.
This night for the first time in my life i've seen this broken pipe
error on my x86 laptop too when running the script. It happened once
but then has not appeared again running the script multiple
consecutive times. On my arm device it happens almost always, as i
told.
It's getting more and more weird...

#787781#29
Date:
2015-06-06 00:54:20 UTC
From:
To:
how many cores does the i386 machine have?  from the initial report, i
see that your armhf machine is marked as "SMP w/2 CPU cores".  How much
RAM does each machine have?

I'm cc'ing Colin Watson (the pass maintainer) here, maybe he can try to
replicate the behavior you've observed in https://bugs.debian.org/787781

#787781#34
Date:
2015-06-06 08:48:32 UTC
From:
To:
The i386 machine is a core 2 Duo with 4Gb of RAM. The armhf one is an
arm chromebook, dual core with 2Gb of RAM.
Anyways on both machines RAM usage is well under a critical value, i
guess 25%-30% at most...

Yes it's a good idea... i'd also try to abstract the issue even more,
so if i manage to use gpg-agent in a way that doesn't involve pass,
(maybe asimmetrically signing/encrypting some files) and the error
shows up again when invoking via stdbuf, than it'd be likely and
strictly an issue on gpg-agent and not pass... (shouldn't it?)

Updates will follow...

#787781#39
Date:
2015-06-06 13:17:21 UTC
From:
To:
*decrypting

Well, using:

stdbuf -oL gpg --use-agent --sign <file>

works without errors retrieving the cached password from gpg-agent.
I'd say the problem is not directly gpg-agent then...

Anyways executing the command above, i noticed it asked me the
passphrase via pinentry curses althogh it was already cached, because
i used it few seconds before with pass, and i used it after just to be
sure (obviously i have signed the test file with the same key pass
uses to encrypt its password store).
Now i don't know gpg-agent internals, but shouldn't it have used the
already cached passphrase? Also the two pinentry dialog showed when
using pass and when using gpg are slightly different in text and size.
But maybe this is OT.

Thanks.

#787781#44
Date:
2015-06-09 03:20:53 UTC
From:
To:
depends on how gpg-agent is configured.  for example, do you have
ignore-cache-for-signing in ~/.gnupg/gpg-agent.conf ?

also, the subkey that is used for encryption should be a different key
than the one used for signing.  It's not clear that gpg-agent should try
to reuse its known passwords for a key that it does not associate with
those passwords.  Anyway, if you think it should, that's probably a
different feature enhancement request to pursue, and we shouldn't
distract #787781 with it.

Regards,

#787781#49
Date:
2015-06-09 08:33:54 UTC
From:
To:
Nop, i don't have ~/.gnupg/gpg-agent.conf, i currently have no need
for settings other than de dafault ones.
Anyways i start noticing this isssue is happening quite often on my
intel machine too, but with some weirdness. I mean, i have six mail
accounts configured for mpop, so it should do six calls to
pass+gpg(+gpg-agent only the first time), and while on arm i get six
broken pipe errors, on my x86 i get from zero to two/three of them
randomly.

Yes sure, sorry for that.