[Icecast] <on-connect> / <on-disconnect> not working

Petr Pisar petr.pisar at atlas.cz
Thu Jul 14 16:18:54 UTC 2022

V Thu, Jul 14, 2022 at 08:16:03AM -0700, Jack Elliott napsal(a):
> Hi,
> Icecast server 2.4.0 running on Linux.
Could you try upgrading Icecast? The latest version is 2.4.4 and there were
some fixes in between.

> I have a couple of shell scripts that send emails on connect and on 
> disconnect. From the command line they work, but when called from 
> icecast they do not.
> I'd like to get these functions working . . . ideas?
A problem is that Icecast does not log a failed execution of the scripts.
Neither an exit code of the finished script.

It can only log some fork errors and file permissions before executing them.
And an attempt to execute a script is logged only if Icecast log level is set
to debug:

static void _run_script (event_exec_t *self, event_t *event) {
    pid_t pid, external_pid;

    /* do a fork twice so that the command has init as parent */
    external_pid = fork();
    switch (external_pid)
        case 0:
            switch (pid = fork ())
                case -1:
                    ICECAST_LOG_ERROR("Unable to fork %s (%s)", self->executable, strerror (errno));
                case 0:  /* child */
                    if (access(self->executable, R_OK|X_OK) != 0) {
                        ICECAST_LOG_ERROR("Unable to run command %s (%s)", self->executable, strerror(errno));
                    ICECAST_LOG_DEBUG("Starting command %s", self->executable);
                    __setup_empty_script_environment(self, event);
                    execv(self->executable, __setup_argv(self, event));
                default: /* parent */
            exit (0);
        case -1:
            ICECAST_LOG_ERROR("Unable to fork %s", strerror (errno));
        default: /* parent */
            waitpid (external_pid, NULL, 0);

You can use "strace" tool to check whether the scripts are actually executed.
Something like "strace -fq -e execve -p PID_OF_THE_RUNNING_SERVER".

The code is pretty terrible. access() does not answer whether a process can
exucute a program. Also execv() can fail for various reasons: Different
effective UID/GID, missing capabilities, violation of SELinux policy. And then
there can be problems with the executed program itself, like a wrong magic
number, unsupported architecture, a missing dynamic library, bad script
interpreter etc.

I recommend Icecast developers to remove the access() call and instead log
errno after a failed execve. Also logging a status code of the terminated
executable returned by waitpid() would be helpful.

-- Petr
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.xiph.org/pipermail/icecast/attachments/20220714/8416455d/attachment.sig>

More information about the Icecast mailing list