I've tried to use sieve-filter for my inbox (~6000 messages). It failed after
some work with this backtrace:

sieve-filter(kas): Error: socketpair() failed: Too many open files
sieve-filter(kas): Panic: file script-client-local.c: line 155 
(script_client_local_disconnect): assertion failed: (pid >= 0)
sieve-filter(kas): Error: Raw backtrace: 
/usr/lib/dovecot/libdovecot.so.0(+0x66a71) [0x7f020e717a71] -> 
/usr/lib/dovecot/libdovecot.so.0(default_fatal_handler+0x2a) [0x7f020e717ada] 
-> /usr/lib/dovecot/libdovecot.so.0(i_fatal+0) [0x7f020e6d32ee] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(+0x4baf) 
[0x7f020dae0baf] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(+0x58ca) 
[0x7f020dae18ca] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(script_client_fail+0x2f)
 [0x7f020dae199f] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(script_client_run+0xc4)
 [0x7f020dae1fd4] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(+0x6134) 
[0x7f020dae2134] -> 
/usr/lib/dovecot/libdovecot-sieve.so.0(sieve_result_execute+0x3ac) 
[0x7f020ecd1adc] -> /usr/lib/dovecot/libdovecot-sieve.so.0(sieve_execute+0x4a) 
[0x7f020ece05aa] -> /usr/bin/sieve-filter(main+0x6a9) [0x403b49] -> 
/usr/lib/libc.so.6(__libc_
 start_ma
 in+0xf5) [0x7f020e327bc5] -> /usr/bin/sieve-filter() [0x404111]

The reason is file descriptor leak in "script client local".
script_client_local_close_output() shutdowns write side of descriptor
and sets sclient->fd_out to -1, but never closes the descriptor.

I've tried to fix this by the patch below. Tests works fine, but sieve-filter
crashed in other way:

sieve-filter(kas): Panic: epoll_ctl(del, 13) failed: Bad file descriptor
sieve-filter(kas): Error: Raw backtrace: 
/usr/lib/dovecot/libdovecot.so.0(+0x66a71) [0x7f0ed406fa71] -> 
/usr/lib/dovecot/libdovecot.so.0(default_fatal_handler+0x2a) [0x7f0ed406fada] 
-> /usr/lib/dovecot/libdovecot.so.0(i_fatal+0) [0x7f0ed402b2ee] -> 
/usr/lib/dovecot/libdovecot.so.0(+0x776f5) [0x7f0ed40806f5] -> 
/usr/lib/dovecot/libdovecot.so.0(+0x8009a) [0x7f0ed408909a] -> 
/usr/lib/dovecot/libdovecot.so.0(io_stream_unref+0x25) [0x7f0ed40764c5] -> 
/usr/lib/dovecot/libdovecot.so.0(o_stream_unref+0x26) [0x7f0ed4088136] -> 
/usr/lib/dovecot/libdovecot.so.0(+0x80e48) [0x7f0ed4089e48] -> 
/usr/lib/dovecot/libdovecot.so.0(io_loop_call_io+0x27) [0x7f0ed407fa47] -> 
/usr/lib/dovecot/libdovecot.so.0(io_loop_handler_run+0xd7) [0x7f0ed40807d7] -> 
/usr/lib/dovecot/libdovecot.so.0(io_loop_run+0x38) [0x7f0ed407f5e8] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(script_client_run+0x9c)
 [0x7f0ed343af8c] -> 
/usr/lib/dovecot/modules/sieve/lib90_sieve_extprograms_plugin.so(+0x6
 114) [0x
 7f0ed343b114] -> 
/usr/lib/dovecot/libdovecot-sieve.so.0(sieve_result_execute+0x3ac) 
[0x7f0ed4629adc] -> /usr/lib/dovecot/libdovecot-sieve.so.0(sieve_execute+0x4a) 
[0x7f0ed46385aa] -> /usr/bin/sieve-filter(main+0x6a9) [0x403b49] -> 
/usr/lib/libc.so.6(__libc_start_main+0xf5) [0x7f0ed3c7fbc5] -> 
/usr/bin/sieve-filter() [0x404111]

I failed to unfold this in a reasonable time. Any ideas?

diff --git a/src/plugins/sieve-extprograms/script-client-local.c 
b/src/plugins/sieve-extprograms/script-client-local.c
index 56d32f707c09..f54ef82132cf 100644
--- a/src/plugins/sieve-extprograms/script-client-local.c
+++ b/src/plugins/sieve-extprograms/script-client-local.c
@@ -139,7 +139,6 @@ static int script_client_local_close_output(struct 
script_client *sclient)
                i_error("shutdown(%s, SHUT_WR) failed: %m", sclient->path);
                return -1;
        }
-       sclient->fd_out = -1;
        return 1;
 }
 
diff --git a/src/plugins/sieve-extprograms/script-client.c 
b/src/plugins/sieve-extprograms/script-client.c
index 06a5d5d54ba9..6fefca4c9f26 100644
--- a/src/plugins/sieve-extprograms/script-client.c
+++ b/src/plugins/sieve-extprograms/script-client.c
@@ -68,7 +68,8 @@ static void script_client_disconnect
 
        if (sclient->fd_in != -1 && close(sclient->fd_in) < 0)
                i_error("close(%s) failed: %m", sclient->path);
-       if (sclient->fd_out != -1 && sclient->fd_out != sclient->fd_out)
+       if (sclient->fd_out != -1 && sclient->fd_out != sclient->fd_in
+                       && close(sclient->fd_out) < 0)
                i_error("close(%s/out) failed: %m", sclient->path);
        sclient->fd_in = sclient->fd_out = -1;
        
-- 
 Kirill A. Shutemov

Reply via email to