Re: notmuch vs. SIGPIPE

2020-01-21 Thread Thomas Schwinge
Hi!

On 2020-01-20T23:36:51+0100, I wrote:
> On 2020-01-20T12:55:28+0100, I wrote:
>> While looking a bit into the item raised in
>> id:87muamgspy@euler.schwinge.homeip.net I noticed the following
>> (mis?)behavior by notmuch.
>>
>> To set the stage:
>>
>> $ yes | head -n 1
>> y
>> $ echo "${PIPESTATUS[@]}"
>> 141 0
>>
>> As expected, the 'yes' process exits with SIGPIPE right after the 'head'
>> process terminated.
>
> See also , for example.
>
>> However:
>>
>> $ notmuch search \* | head -n 1 & sleep 22; jobs; ps -f
>> [1] 622009
>> thread:00032bb2   the future [1/1] Jenna Moss; Steve Burbon, 
>> Washington (hurd list spam)
>> [1]+  Running notmuch search \* | head -n 1 &
>> UID  PIDPPID  C STIME TTY  TIME CMD
>> thomas6218514297  0 12:38 pts/38   00:00:00 /bin/bash
>> thomas622008  621851 99 12:48 pts/38   00:00:22 
>> /home/thomas/command/notmuch.real search \*
>> thomas622013  621851  0 12:48 pts/38   00:00:00 ps -f
>>
>> Even after its "pipe-consumer" 'head' process has terminated, the
>> 'notmuch' process still keeps running, and running, and running...

> So, libgpgme via libgmime initialization is doing something with signals.
> Here, 'sig=13' is SIGPIPE

> Breakpoint 1, __GI___sigaction (sig=13, act=0x7fffd4e0, oact=0x0) at 
> ../nptl/sigaction.c:24

> (gdb) print *act
> $3 = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, 
> sa_mask = {__val = {0 }}, sa_flags = 0, sa_restorer = 0x0}
>
> A '0x1' '__sigaction_handler' means 'SIG_IGN', ignore any such signals.
> This is unexpected (to me, at least), not what I'd expect with notmuch?
>
> According to a (very quick) check/survey, this has apparently been the
> case "forever", and is documented on
> ,
> together with some rationale.  Aha, aha, OK, I see.
>
> So, assuming we want to keep it that way (given the gpgme rationale), is
> the problem then that we fail to handle appropriately in notmuch any
> EPIPE that we may be getting from 'write' etc.?  This remains to be
> explored another day.

Indeed.  Using a FIFO to simulate a pipe:

$ mkfifo f
$ head -n 1 < f &
[1] 775394

(This will trigger SIGPIPE/EPIPE after one line.)

$ gdb -q notmuch
Reading symbols from notmuch...
(gdb) break write
Breakpoint 1 at 0xd420
(gdb) run dump > f
Starting program: [...]/notmuch dump > f
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, __GI___libc_write (fd=8, buf=0x55683710, nbytes=8192) at 
../sysdeps/unix/sysv/linux/write.c:26
26  ../sysdeps/unix/sysv/linux/write.c: No such file or directory.
(gdb) bt
#0  0x7789a8f0 in __GI___libc_write (fd=8, buf=0x55683710, 
nbytes=8192) at ../sysdeps/unix/sysv/linux/write.c:26
#1  0x77d8ff99 in gz_comp (state=state@entry=0x55683620, 
flush=0) at gzwrite.c:89
#2  0x77d909ff in gzvprintf (file=0x55683620, format=, va=va@entry=0x7fffd190) at gzwrite.c:442
#3  0x77d90ad4 in gzprintf (file=file@entry=0x55683620, 
format=format@entry=0x5558f54e " -- %s\n") at gzwrite.c:457
#4  0x5556964e in dump_tags_message (size_p=0x7fffd2d0, 
buffer_p=0x7fffd2c8, output=0x55683620, output_format=1, 
message=0x556884e0, ctx=0x555d01b0) at notmuch-dump.c:203
#5  0x5556964e in database_dump_file (include=, 
output_format=1, query_str=, output=0x55683620, 
notmuch=0x555d01b0) at notmuch-dump.c:254
#6  0x5556964e in notmuch_database_dump (notmuch=0x555d01b0, 
output_file_name=0x0, query_str=, 
output_format=DUMP_FORMAT_BATCH_TAG, include=, 
gzip_output=) at notmuch-dump.c:314
#7  0x55569e4b in notmuch_dump_command (config=, 
argc=, argv=0x7fffd860) at notmuch-dump.c:413
#8  0x55565426 in main (argc=2, argv=0x7fffd858) at 
notmuch.c:505

This is the libz 'printf' pass-through code via 'notmuch dump'.

(gdb) finish
Run till exit from #0  __GI___libc_write (fd=8, buf=0x55683710, 
nbytes=8192) at ../sysdeps/unix/sysv/linux/write.c:26
#notmuch-dump batch-tag:3 config,properties,tags

First line got printed.

gz_comp (state=state@entry=0x55683620, flush=0) at gzwrite.c:90
90  gzwrite.c: No such file or directory.
Value returned is $1 = 8192

Supposedly 8192 bytes have been written, which seems a bit dubious, but I
have not studies the fine details of how FIFO buffering vs. SIGPIPE/EPIPE
work -- presumably indeed 8192 bytes were written into the FIFO buffer,
but then only line read, then the FIFO/buffer closed, so the other bytes
lost, and then only on the next 'write', we get...

(gdb) c
Continuing.

Breakpoint 1, __GI___libc_write (fd=8, bu

Re: notmuch vs. SIGPIPE

2020-01-20 Thread Thomas Schwinge
Hi!

On 2020-01-20T12:55:28+0100, I wrote:
> While looking a bit into the item raised in
> id:87muamgspy@euler.schwinge.homeip.net I noticed the following
> (mis?)behavior by notmuch.
>
> To set the stage:
>
> $ yes | head -n 1
> y
> $ echo "${PIPESTATUS[@]}"
> 141 0
>
> As expected, the 'yes' process exits with SIGPIPE right after the 'head'
> process terminated.

See also , for example.

> However:
>
> $ notmuch search \* | head -n 1 & sleep 22; jobs; ps -f
> [1] 622009
> thread:00032bb2   the future [1/1] Jenna Moss; Steve Burbon, 
> Washington (hurd list spam)
> [1]+  Running notmuch search \* | head -n 1 &
> UID  PIDPPID  C STIME TTY  TIME CMD
> thomas6218514297  0 12:38 pts/38   00:00:00 /bin/bash
> thomas622008  621851 99 12:48 pts/38   00:00:22 
> /home/thomas/command/notmuch.real search \*
> thomas622013  621851  0 12:48 pts/38   00:00:00 ps -f
>
> Even after its "pipe-consumer" 'head' process has terminated, the
> 'notmuch' process still keeps running, and running, and running...  It
> has to be killed manually (unless it before exits because of concurrent
> database modification).  This doesn't seem expected behavior to me?
>
> Now, I do have a patch or two (actually dozensa; reverts, WIP etc.) on
> top of months-old notmuch sources, so I'll later try to reproduce that
> with clean sources.

$ gdb -q --args notmuch dump
Reading symbols from notmuch...
(gdb) break sigaction
Breakpoint 1 at 0xe130
(gdb) r
Starting program: [...]/notmuch dump
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, __GI___sigaction (sig=13, act=0x0, oact=0x7fffd4e0) at 
../nptl/sigaction.c:24
24  ../nptl/sigaction.c: No such file or directory.
(gdb) bt
#0  0x777e92f0 in __GI___sigaction (sig=13, act=0x0, 
oact=0x7fffd4e0) at ../nptl/sigaction.c:24
#1  0x775bfa8d in  () at /usr/lib/x86_64-linux-gnu/libgpgme.so.11
#2  0x775c64cd in gpgme_check_version () at 
/usr/lib/x86_64-linux-gnu/libgpgme.so.11
#3  0x775c6667 in gpgme_check_version_internal () at 
/usr/lib/x86_64-linux-gnu/libgpgme.so.11
#4  0x77f456b3 in g_mime_init () at 
/usr/lib/x86_64-linux-gnu/libgmime-3.0.so.0
#5  0x5556539d in main (argc=2, argv=0x7fffd828) at 
notmuch.c:469

So, libgpgme via libgmime initialization is doing something with signals.
Here, 'sig=13' is SIGPIPE, 'act=0x0' means to just query, and store
current handling into 'oact':

(gdb) finish
Run till exit from #0  __GI___sigaction (sig=13, act=0x0, 
oact=0x7fffd4e0) at ../nptl/sigaction.c:24
0x775bfa8d in ?? () from /usr/lib/x86_64-linux-gnu/libgpgme.so.11
Value returned is $1 = 0
(gdb) print *(struct sigaction *) 0x7fffd4e0
$2 = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask 
= {__val = {0, 8, 93824992565632, 0, 32, 88, 0, 22, 0, 140733193388034, 
93823560581120, 7, 93824992559120, 32, 5, 93824992694848}}, sa_flags = 0, 
sa_restorer = 0x0}

A '0x0' '__sigaction_handler' means 'SIG_DFL', which for SIGPIPE means to
terminate the process.  This is as expected.  However, then:

(gdb) continue 
Continuing.

Breakpoint 1, __GI___sigaction (sig=13, act=0x7fffd4e0, oact=0x0) at 
../nptl/sigaction.c:24
24  in ../nptl/sigaction.c
(gdb) bt
#0  0x777e92f0 in __GI___sigaction (sig=13, act=0x7fffd4e0, 
oact=0x0) at ../nptl/sigaction.c:24
#1  0x775bfadc in  () at /usr/lib/x86_64-linux-gnu/libgpgme.so.11
#2  0x775c64cd in gpgme_check_version () at 
/usr/lib/x86_64-linux-gnu/libgpgme.so.11
#3  0x775c6667 in gpgme_check_version_internal () at 
/usr/lib/x86_64-linux-gnu/libgpgme.so.11
#4  0x77f456b3 in g_mime_init () at 
/usr/lib/x86_64-linux-gnu/libgmime-3.0.so.0
#5  0x5556539d in main (argc=2, argv=0x7fffd828) at 
notmuch.c:469
(gdb) print *act
$3 = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, sa_mask 
= {__val = {0 }}, sa_flags = 0, sa_restorer = 0x0}

A '0x1' '__sigaction_handler' means 'SIG_IGN', ignore any such signals.
This is unexpected (to me, at least), not what I'd expect with notmuch?

According to a (very quick) check/survey, this has apparently been the
case "forever", and is documented on
,
together with some rationale.  Aha, aha, OK, I see.

So, assuming we want to keep it that way (given the gpgme rationale), is
the problem then that we fail to handle appropriately in notmuch any
EPIPE that we may be getting from 'write' etc.?  This remains to be
explored another day.


Grüße
 Thomas
___
notmuch mailing list
notmuch@notmuc

notmuch vs. SIGPIPE

2020-01-20 Thread Thomas Schwinge
Hi!

While looking a bit into the item raised in
id:87muamgspy@euler.schwinge.homeip.net I noticed the following
(mis?)behavior by notmuch.

To set the stage:

$ yes | head -n 1
y
$ echo "${PIPESTATUS[@]}"
141 0

As expected, the 'yes' process exits with SIGPIPE right after the 'head'
process terminated.  However:

$ notmuch search \* | head -n 1 & sleep 22; jobs; ps -f
[1] 622009
thread:00032bb2   the future [1/1] Jenna Moss; Steve Burbon, 
Washington (hurd list spam)
[1]+  Running notmuch search \* | head -n 1 &
UID  PIDPPID  C STIME TTY  TIME CMD
thomas6218514297  0 12:38 pts/38   00:00:00 /bin/bash
thomas622008  621851 99 12:48 pts/38   00:00:22 
/home/thomas/command/notmuch.real search \*
thomas622013  621851  0 12:48 pts/38   00:00:00 ps -f

Even after its "pipe-consumer" 'head' process has terminated, the
'notmuch' process still keeps running, and running, and running...  It
has to be killed manually (unless it before exits because of concurrent
database modification).  This doesn't seem expected behavior to me?

Now, I do have a patch or two (actually dozensa; reverts, WIP etc.) on
top of months-old notmuch sources, so I'll later try to reproduce that
with clean sources.


Grüße
 Thomas


signature.asc
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch