collectd/collectd — Issue #12: bug of "exec plugin:STDERR close"
Author: octo
Created: 2012-02-19 21:01:58+00:00
State: open

From: Tetsuya Kawaguchi (Mantis #44)

**Description:** When using "exec plugin", you might face to the message "exec plugin: Program 'xxxx' has closed STDERR.", Under this condition, collectd will sent `SIGTERM` to the process which has no relation to collectd. This will happen in collectd's termination sequence.

We think `exec_read_one()` thread of `exec.c` has a problem. If there are any child processes to close stderr, the thread will not be closed because it permanently waits for the closed process in the select function.

```c
static void *exec_read_one (void *arg) /* {{{ */
{
*snip*

FD_ZERO( &fdset );
FD_SET(fd, &fdset);
FD_SET(fd_err, &fdset);

/* Determine the highest file descriptor */
highest_fd = (fd > fd_err) ? fd : fd_err;

/* We use a copy of fdset, as select modifies it */
copy = fdset;

while (select(highest_fd + 1, ©, NULL, NULL, NULL ) > 0)
{
*snip*
if (FD_ISSET(fd, ©))
{
*snip*
}
else if (FD_ISSET(fd_err, ©))
{
*snip*
if (len < 0)
{
*snip*
}
else if (len == 0)
{
/* We've reached EOF */
NOTICE ("exec plugin: Program `%s' has closed STDERR.",
pl->exec);
close (fd_err);

FD_CLR (fd_err, &fdset);
highest_fd = fd;
copy = fdset; /* <- this line seems to be required. */
fd_err = -1;
continue;
}
*snip*
}
```

Because a copy of `fdset` is used as a parameter in the select function, it is necessary to copy `fdset` which FD_CLRed.

**Steps to reproduce:** execute a module like the following from "exec plugin".

```c
#include

int main( void ){
fclose( stderr );
return 0;
}
```

Process ID remains still on `*pl_head` of exec plugin (exec.c).