Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Daemon returned 2 as return value. #2

Closed
joerg-krause opened this issue Jul 17, 2014 · 27 comments
Closed

Daemon returned 2 as return value. #2

joerg-krause opened this issue Jul 17, 2014 · 27 comments
Assignees

Comments

@joerg-krause
Copy link

Hi Mike,

thanks for the fantastic rework on shairport. I suscessfully cross-compiled shairport-sync as a package within buildroot. But trying to start shairport as a daemon fails with:

Daemon returned 2 as return value.

I previous used shairport from abrasive, which ran fine as a daemon. Any suggestions?

@mikebrady
Copy link
Owner

Thanks for your kind words.
Another user built shairport-sync in buildroot and reported what appears to be the same issue. Assuming it actually is the same issue, the cause and the fix are simple.

The problem is that buildroot places shairport-sync in /usr/bin/shairport, but the init script file /etc/init.d/shairport (also at https://github.com/mikebrady/shairport-sync/blob/2.0/scripts/shairport), line 20 says to use the program /usr/local/bin/shairport, so basically, the init file is looking in the wrong place! Editing that line to say /usr/bin/$NAME would fix that.

Another related issue is that the init script expects the directory /usr/var/run/ to be in existence – you might have to add a line to create it.

@mikebrady mikebrady self-assigned this Jul 17, 2014
@zoomzoomluke
Copy link

I found that simply creating /usr/var/run solved the error 2

Naturally you could also fix this at source by changing /usr/var/run/shairport.pid to /var/run/shairport.pid

@joerg-krause
Copy link
Author

@mikebrady : I did not use the provided init script file, but run "shairport -d" from console.
@zoomzoomluke : I already thought about the pid file, thanks for the advise!
@mikebrady : What do you think of a shairport.conf file where the user can define the pid and log files?

@mikebrady
Copy link
Owner

Shairport should leave a message in the logfile. Can you see if it's there?

Also – just backing up a bit – does shairport -v work (i.e. verbose mode, and not daemon mode)?

Also, thanks for your suggestions. At present, I'm focused more on trying to get overall functionality right; I'll certainly look at your suggestions later.

@mikebrady
Copy link
Owner

Another possibility is to run shairport in supervisor mode, e.g.
sudo shairport -d

@mikebrady
Copy link
Owner

@joerg-krause, I'm wondering if I can close the issue as solved?

@joerg-krause
Copy link
Author

Sorry, I did not had the time to make any further tests.

Non daemon mode worked and there is only root on my embedded system.

I guess that zoomzoomluke is right with his suggestion to create /usr/var/run.

@mikebrady
Copy link
Owner

Okay, if it's okay with you I'll close this issue. Version 2.1 is out, which doesn't change this behaviour, but you might be interested anyway: https://github.com/mikebrady/shairport-sync/blob/2.1/README.md.

@joerg-krause
Copy link
Author

I'm still having this "Daemon returned 2 as return value" error. I think libdaemon tries to start at /usr/var/run/ which does not exists (but /var/run do). I changed the init script file:

    NAME=shairport-sync
    DAEMON=/usr/bin/$NAME
    PIDFILE=/var/run/$NAME.pid

I also tried to configure with

    --localstatedir=/var

but it does not help.

@mikebrady
Copy link
Owner

Hi there. A couple of things:

  1. The return of 2 indicates that the binary of shairport-sync could not be started. To help diagnose this problem, could you enter the command which shairport-sync and post the result here?
  2. The location of the PID file is /var/run/shairport-sync.pid by default, and that should be fine, as the directory /var/run exists.
  3. AFAIK, the –localstatedir flag shouldn't have any effect at all.

@joerg-krause
Copy link
Author

  1. which shairport-sync results in /usr/bin/shairport-sync
  2. The location of the PID file is /usr/var/run/shairport-sync.pid. I had to create the directory /usr/var/run.
  3. This is a solution I found here: https://bugs.archlinux.org/task/15192

@mikebrady
Copy link
Owner

Thanks. The result from which means the binary is where it should be. That's good.
I should have asked earlier: what distribution of Linux are you using? Maybe I can reproduce the environment – and the fault! – here.

@joerg-krause
Copy link
Author

I'm using buildroot to build my custom linux system.

@mikebrady
Copy link
Owner

Thanks. I might give it a try. Are you building for an x86 32-bit?

@joerg-krause
Copy link
Author

Building for arm926t. The package shairport-sync is not upstream yet. I am still testing...but I can send you an patch, if necessary.

@mikebrady
Copy link
Owner

I think I might have found it. For some reason, libdaemon looks for a directory called /usr/var/run/ and if it doesn't exist, shairport-sync refuses to start in daemon mode. So the obvious fix, as you wrote previously, is to execute the command mkdir -p /usr/var/run/ before launching shairport-sync.

Here is a sample startup script for shairport-sync incorporating this idea. The file is at /etc/init.d/S95shairport-sync:

#!/bin/sh
#
# bare-bones shairport-sync init script sample

DAEMON=/usr/bin/shairport-sync
case "$1" in
    start)
    mkdir -p /usr/var/run/
    $DAEMON -d -a "Buildroot Shairport Sync"
    ;;
    stop)
    $DAEMON -k
    ;;
    *)
    echo "Usage: S95shairport-sync {start|stop}" >&2
    exit 1
    ;;
esac

This works on my buildroot system for the Raspberry Pi.

@joerg-krause
Copy link
Author

You are right! The default behaviour of libdaemon is to run in /usr/var/run. This can be overrriden by setting localstatedir to autotools configure. OpenWrt sets this to /var globally, but buildroot doesn't.

Running in /usr/var/run is not a good idea, since it may be mounted read-only on some systems.

There are two possibilities to solve this issue for buildroot:

  1. Adding --localstatedir=/var to the config options of the package libdaemon
  2. Setting --localstatedir=/var globally. This is discussed at the mailing list for now...

@joerg-krause
Copy link
Author

Problem solved. Can be closed now :-)

@mikebrady
Copy link
Owner

Thanks for your explanation of its significance. It does appear as if libdaemon can be explicitly told how to calculate where to put the PID file (e.g. see Avahi), but I'll have to add a little code to shairport-sync to do it. I'll give it a try in the next little while.

@mikebrady
Copy link
Owner

I updated Shairport Sync to take a new --with-localstatedir configure option in release 2.1.4, and it seems to work.

Update -- actually, it's not quite ready. Doesn't work right on a debian system :(
Update 2 -- working now, but is a --with-localstatedir, will be 2.1.5

@mikebrady
Copy link
Owner

To clarify the above, Shairport Sync now takes a new --with-localstatedir configure option in release 2.1.5, and it seems to work in buildroot, e.g. using --with-localstatedir=/var.

@joerg-krause
Copy link
Author

First, many thanks for the work. But let me explain:

I submitted a patch to buildroot which will set --localstatedir=/var as a default option applied to all packages build with autotools. Why is it necessary?

About localstatedir

localstatedir is a GNU Makefile variable and the GNU Coding Standard defines to set it as --localstatedir=/usr/local/var by default. On the other hand, the Filesystem Hierarchy Standard (FHS) defines the directory /usr as shareable, read-only directory and forbids writing to it.

What's all this about?

Allmost all linux distributions follow the FHS for their filesystem hierarchy. And some deviate from the standard in some areas. For example most distros, eg. Debian, use the /run directory as a replacement for /var/run and all of the other run-time directories. The directory /run and it's usage as default runtime directory will be added to the next version of the FHS. In the meantime the distros creates symlinks for all files of /var/run to /run.

How about buildroot?

Buildroot follows the FHS (and also uses the symlinks to /run). libdaemon sets localstatedir to /usr/var by default. This directory does not exist on a linux system build by buildroot. And it's not sure if it exists on other distros, too. And if it exists, it may be read-only.

That's why the user can override the default setting of localstatedir with the directory needed by the used linux system. This should be /var in most cases for a FHS compliant distro.

Summarized

The package libdaemon should be build with localstatedir set to the need of the underlying linux system. This will be done automatically for most linux distros. However, this was not done by buildroot. Instead libdaemon tooks the default setting /var/run as run-time directory. This will be fixed by setting localstatedir globally to /var for all autotools packages. It was a bug in the libdaemons buildroot Makefile to not set it correctly.

That's why I think it's not necessary to change localstatedir by shairport-sync. This is the duty of the package mantainer of libdaemon.

@mikebrady
Copy link
Owner

Thanks again for the posts – very interesting. I agree that it should not be necessary for shairport-sync to change the localstatedir, but in the meantime, I offer the with-localstatedir as a safe workaround for building in buildroot.

The update made and then withdrawn yesterday (2.1.4) did attempt to use localstatedir via the
--localstatedir configuration option. Unfortunately, when the value localstatedir is used in a configuration script, one can't determine whether it is the default value or whether it was explicitly set via the --localstatedir option. This is important because, by default in Debian, Ubuntu and Raspian, localstatedir is set according to the GNU Coding Standard to /usr/local/var. In other words, it's set to the wrong directory. So, using localstatedir gives the wrong directory unless the --localstatedir option was used, and one can't tell if it was used or not.

Using with-localstatedir avoids the problem, as the configuration script can determine if the option was used, and will only add the code needed to redirect libdaemon if it was used.

Of course, I could be wrong – the above reflects my understanding, and I'm no Autotools expert. Comments welcome!

@joerg-krause
Copy link
Author

I don't think that Debian uses /usr/local/var for localstatedir. If you take a look at the package libdaemon from Debian, you can see in the Changelog, that they use --localstatedir=/var since version 0.13-2 (https://tracker.debian.org/media/packages/libd/libdaemon/changelog-0.14-2). It is now set in libdaemon/bootstrap.sh (https://sources.debian.net/src/libdaemon/0.14-6/bootstrap.sh/)

If you do not set localstatedir manually for libdaemon, the pid file will be created at ${prefix}/var/run by default:

  • libdaemon/configure: localstatedir='${prefix}/var'
  • libdaemon/pidc: #define VARRUN LOCALSTATEDIR "/run"

Buildroot and Debian set prefix to usr, which results in localstatedir=/usr/var/run by default for those systems (if localstatedir is not set by the user). Which gives us a wrong directory conforming to FHS (which Buildroot and Debian do).

To be pedantic, you cannot override the localstatedir for libdaemon as it is defined at compile time. But you can, and this is what you are doing, change the location of the pid file.

Furthermore the bug in Buildroot not setting localstatedir in the package Makefile of libdaemon is fixed now.

What I would suggest is to change the --with-localstatedir option to --with-pidfile as it better describes what is really done at source level. And this can be a useful feature if you are not happy with the directory your linux distro provides.

@mikebrady
Copy link
Owner

I'm glad to hear the bug in Buildroot is fixed – TBH, I though it might take longer. Following your suggestion, almost, I will rename the directive to --with-piddir.

@joerg-krause
Copy link
Author

Many thanks! --with-piddir sounds like a good solution. Samba uses this, too.

I have another remark, but I will open a new issue. So this can be closed now, I think.

@mikebrady
Copy link
Owner

Thanks. I'll roll that directive mod into an update. Closing the issue!

mikebrady added a commit that referenced this issue Nov 26, 2016
Fix ClientIP info in metadata [development branch; attempt #2] Many thanks!
@ghost ghost mentioned this issue Dec 4, 2016
mikebrady pushed a commit that referenced this issue Jan 21, 2017
Merge from mikebrady/master
mikebrady added a commit that referenced this issue Apr 8, 2019
klemensn added a commit to klemensn/shairport-sync that referenced this issue Jan 31, 2024
atexit(3) handler immediately before main() exits seems redundant.

On OpenBSD 7.4-current, failure to listen on the RTSP socket triggers
```
$ nc -4l 5000 &
$ nc -6l 5000 &
$ shairport-sync -c/dev/null
warning: could not establish a service on port 5000 -- program terminating. Is another instance of Shairport Sync running on this device?
Segmentation fault (core dumped)
```
```
Program terminated with signal SIGSEGV, Segmentation fault.
#0  pthread_cancel (thread=0x6207604e640) at /usr/src/lib/librthread/rthread.c:433
433             if (tib->tib_canceled == 0 && tid != 0 &&
[Current thread is 1 (process 290061)]
#0  pthread_cancel (thread=0x6207604e640) at /usr/src/lib/librthread/rthread.c:433
mikebrady#1  0x0000061e5377df14 in exit_rtsp_listener ()
mikebrady#2  0x000006212fdb4140 in _libc___cxa_finalize (dso=0x0) at /usr/src/lib/libc/stdlib/atexit.c:177
mikebrady#3  0x000006212fde9c45 in _libc_exit (status=0) at /usr/src/lib/libc/stdlib/exit.c:54
mikebrady#4  0x0000061e5377ba88 in _start ()
```

Fix this by omitting the explicit pthread_cancel(3), at which point
exit_rtsp_listener() becomes redundant, so remove it entirely.
klemensn added a commit to klemensn/shairport-sync that referenced this issue Jan 31, 2024
Process teardown stops all threads, thus calling pthread_cancel(3) in an
atexit(3) handler immediately before main() exits seems redundant.

On OpenBSD 7.4-current, failure to listen on the RTSP socket triggers
```
$ nc -4l 5000 &
$ nc -6l 5000 &
$ shairport-sync -c/dev/null
warning: could not establish a service on port 5000 -- program terminating. Is another instance of Shairport Sync running on this device?
Segmentation fault (core dumped)
```
```
Program terminated with signal SIGSEGV, Segmentation fault.
#0  pthread_cancel (thread=0x6207604e640) at /usr/src/lib/librthread/rthread.c:433
433             if (tib->tib_canceled == 0 && tid != 0 &&
[Current thread is 1 (process 290061)]
#0  pthread_cancel (thread=0x6207604e640) at /usr/src/lib/librthread/rthread.c:433
mikebrady#1  0x0000061e5377df14 in exit_rtsp_listener ()
mikebrady#2  0x000006212fdb4140 in _libc___cxa_finalize (dso=0x0) at /usr/src/lib/libc/stdlib/atexit.c:177
mikebrady#3  0x000006212fde9c45 in _libc_exit (status=0) at /usr/src/lib/libc/stdlib/exit.c:54
mikebrady#4  0x0000061e5377ba88 in _start ()
```

Fix this by omitting the explicit pthread_cancel(3), at which point
exit_rtsp_listener() becomes redundant, so remove it entirely.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants