commit:     e4bdce024162b77ee4947674c2e4399fc4cf23f7
Author:     Sven Eden <yamakuzure <AT> gmx <DOT> net>
AuthorDate: Thu Dec  8 09:21:44 2016 +0000
Commit:     David Seifert <soap <AT> gentoo <DOT> org>
CommitDate: Wed Jan  4 13:41:54 2017 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=e4bdce02

sci-misc/boinc: Update init script to fix bug 584386 and 603522

Gentoo-Bug: 584386

The boinc init script starts boinc_client in daemon mode, and relies on
boinccmd to send a quit signal to stop the service.

This leads to the following two problems:
1) It is not possible to generate a pid file, as the pid read from the
   started boinc_client is invalid after it forked to background.
2) The stop command immediately returns, but boinc_client can still be
   active for a long time, over a minute in fact, while it is stopping
   running projects and cleaning up its work data. This is especially
   problematic when boinc is stopped while shutting down the machine.

Gentoo-Bug: 603522

The init script for boinc calls "chown -R" on "${RUNTIMEDIR}".
This leads to the security issue, that the "boinc" user can create a
hardlink within ${RUNTIMEDIR} pointing to a file that he does not
own, and the next time the daemon is started, the init script (as
root) will give ownership of the *target* of the hardlink to the
boinc user.

This commit removes the usage of "chown -R" from start_pre(), and
adds a single call to "chown" to create_work_directory() if, and only
if the working directory has been newly created.

Other fixes and changes:

Another problem found is the function cuda_check(), which assumes the cuda
libraries to be installed in /opt/cuda/lib, leading to an invalid symlink
for libcudart.so on 64 bit machines where the library is installed in
/opt/cuda/lib64.

This commit changes the following behaviour, besides some long overdue
cleanup:
1) start() no longer uses the --daemon option of the boinc_client, but
   the --background option of the start-stop-daemon command. Further it
   creates a pid file in the path set by the new config variable
   BOINC_PIDFILE, that has been added to boinc.conf.
2) stop() no longer uses boinccmd to send a quit signal, but uses the
   --stop and --pidfile options of the start-stop-daemon command. The
   waiting time should be large enough to successfully await the end of
   the exiting task of the boinc_client program.
3) cuda_check() now checks the validity of the libcudart.so symlink and
   removes it if it is invalid. Further it looks for a present
   libcudart.so library in /opt/cuda/lib* and picks the newest found to
   create a new symlink if none is present.
4) The suspend() and resume() functions have been updated to use the
   start-stop-daemon command, so both the user:group and a possibly
   required password are now used to circumvent authentication errors.

Package-Manager: portage-2.3.3
Closes: https://github.com/gentoo/gentoo/pull/3056

 sci-misc/boinc/files/boinc.conf |   6 +++
 sci-misc/boinc/files/boinc.init | 106 +++++++++++++++++++++++++++++++---------
 2 files changed, 89 insertions(+), 23 deletions(-)

diff --git a/sci-misc/boinc/files/boinc.conf b/sci-misc/boinc/files/boinc.conf
index 0fef6ae..22fcca0 100644
--- a/sci-misc/boinc/files/boinc.conf
+++ b/sci-misc/boinc/files/boinc.conf
@@ -10,6 +10,12 @@ RUNTIMEDIR="/var/lib/boinc"
 # Location of the boinc command line binary
 BOINCBIN="/usr/bin/boinc_client"
 
+# Location of the boinc_client pid file
+BOINC_PIDFILE="/var/run/boinc_client.pid"
+
+# Location of the boinccmd command
+BOINCCMD="/usr/bin/boinccmd"
+
 # Allow remote gui RPC yes or no
 ALLOW_REMOTE_RPC="no"
 

diff --git a/sci-misc/boinc/files/boinc.init b/sci-misc/boinc/files/boinc.init
index 07b8b80..4067105 100644
--- a/sci-misc/boinc/files/boinc.init
+++ b/sci-misc/boinc/files/boinc.init
@@ -5,7 +5,6 @@
 
 extra_started_commands="attach resume suspend"
 
-
 depend() {
        # we can use dns and net, but we can also in most cases live without 
them
        use dns net ntp-client ntpd
@@ -13,15 +12,19 @@ depend() {
 
 
 create_work_directory() {
-       if [ ! -d "${RUNTIMEDIR}" ]; then
+       if [[ ! -d "${RUNTIMEDIR}" ]]; then
                einfo "Directory ${RUNTIMEDIR} does not exist, creating now."
                mkdir -p "${RUNTIMEDIR}"
-               if [ ! -d "${RUNTIMEDIR}" ]; then
+               if [[ ! -d "${RUNTIMEDIR}" ]]; then
                        eeror "Directory ${RUNTIMEDIR} could not be created!"
                        return 1
                fi
+
+               # ensure proper ownership
+               chown "${USER}:${GROUP}" "${RUNTIMEDIR}"
        fi
-       if [ ! -e "${RUNTIMEDIR}"/ca-bundle.crt ] ; then
+
+       if [[ ! -e "${RUNTIMEDIR}"/ca-bundle.crt ]]; then
                ln -s /etc/ssl/certs/ca-certificates.crt 
"${RUNTIMEDIR}"/ca-bundle.crt
        fi
 
@@ -30,9 +33,20 @@ create_work_directory() {
 
 
 cuda_check() {
-       if [ -f /opt/cuda/lib/libcudart.so ]; then
-               # symlink wont harm :]
-               ln -snf /opt/cuda/lib/libcudart.so "${RUNTIMEDIR}"/libcudart.so
+       local libtarget="${RUNTIMEDIR}/libcudart.so"
+       local libsource="$(ls -t /opt/cuda/lib*/libcudart.so 2>/dev/null | head 
-n 1)"
+
+       # Remove a broken symlink
+       if [[ -h "${libtarget}" ]] \
+       && [[ "${libsource}" != "$(readlink "${libtarget}")" ]]; then
+               rm -f "${libtarget}"
+       fi
+
+       # symlink the correct path
+       if [[ -n "${libsource}" ]] \
+       && [[ -f "${libsource}" ]] \
+       && [[ ! -h "${libtarget}" ]]; then
+               ln -snf "$libsource" "${libtarget}"
        fi
 }
 
@@ -43,17 +57,26 @@ env_check() {
        : ${GROUP:="boinc"}
        : ${RUNTIMEDIR:="/var/lib/boinc"}
        : ${BOINCBIN:="$(which boinc_client)"}
+       : ${BOINC_PIDFILE:="/var/run/boinc_client.pid"}
+       : ${BOINCCMD:="$(which /usr/bin/boinccmd)"}
        : ${ALLOW_REMOTE_RPC:="yes"}
        : ${NICELEVEL:="19"}
        # ARGS is not checked, it could have been explicitly set
        # to be empty by the user.
 
        # If the client was not found (how?) something is seriously wrong
-       if [ ! -x "$BOINCBIN" ] ; then
+       if [[ ! -x "$BOINCBIN" ]]; then
                eerror "No boinc_client found!"
                return 1
        fi
 
+       # The boinccmd is crucial, or we can not attach, suspend or resume
+       # the boinc client
+       if [[ ! -x "$BOINCCMD" ]]; then
+               eerror "No boinccmd_program found!"
+               return 1
+       fi
+
        return 0
 }
 
@@ -75,10 +98,7 @@ start_pre() {
        create_work_directory || return 1
        cuda_check
 
-       # always ensure proper ownership
-       chown -R "${USER}:${GROUP}" "${RUNTIMEDIR}"
-
-       if [ ! -f "${RUNTIMEDIR}/lockfile" ]; then
+       if [[ ! -f "${RUNTIMEDIR}/lockfile" ]]; then
                einfo "File \"${RUNTIMEDIR}/lockfile\" does not exist, assuming 
first run."
                einfo "You need to setup an account on the BOINC project 
homepage beforehand!"
                einfo "Go to http://boinc.berkeley.edu/ and locate your 
project."
@@ -94,14 +114,17 @@ start_pre() {
 
 
 start() {
-       if [ "${ALLOW_REMOTE_RPC}" = "yes" ]; then
+       if [[ "${ALLOW_REMOTE_RPC}" = "yes" ]]; then
                ARGS="${ARGS} --allow_remote_gui_rpc"
        fi
 
-       ARGS="${ARGS} --daemon --dir "${RUNTIMEDIR}" --redirectio"
+       ARGS="${ARGS} --dir "${RUNTIMEDIR}" --redirectio"
 
        ebegin "Starting ${RC_SVCNAME}"
-       start-stop-daemon -S -N ${NICELEVEL} -u ${USER} -q -x "${BOINCBIN}" -- 
${ARGS}
+       start-stop-daemon --start --nicelevel ${NICELEVEL} \
+               --user "${USER}:${GROUP}" --quiet --make-pidfile \
+               --pidfile "$BOINC_PIDFILE" --background \
+               --exec "${BOINCBIN}" -- ${ARGS}
        eend $?
 }
 
@@ -113,7 +136,7 @@ attach() {
 
        env_check || return 1
 
-       einfo "If you cant find your account key just try to obtain it by 
using:"
+       einfo "If you can't find your account key just try to obtain it by 
using:"
        einfo "    boinccmd --passwd PASSWORD_FROM_GUI_RPC_AUTH 
--lookup_account URL EMAIL PASSWORD"
 
        printf "    Enter the Project URL: "
@@ -130,16 +153,19 @@ attach() {
        fi
 
        ebegin "${RC_SVCNAME}: Attaching to project"
-       start-stop-daemon -u ${USER} -q -d "${RUNTIMEDIR}" -x boinccmd -- 
${password} --project_attach ${url} ${key}
+       start-stop-daemon --user "${USER}:${GROUP}" --quiet \
+               --chdir "${RUNTIMEDIR}" --exec "${BOINCCMD}" \
+               -- ${password} --project_attach ${url} ${key}
        eend $?
 
-       sleep 10
+       sleep 10s
        tail "${RUNTIMEDIR}/stdoutdae.txt"
 }
 
 
 stop() {
        local password=""
+       local stop_timeout="SIGTERM/60/SIGTERM/30/SIGKILL/30"
 
        env_check || return 1
 
@@ -148,20 +174,54 @@ stop() {
        fi
 
        ebegin "Stopping ${RC_SVCNAME}"
-       start-stop-daemon -u ${USER} -q -d "${RUNTIMEDIR}" -x boinccmd -- 
${password} --quit
+       start-stop-daemon --stop --quiet --progress \
+               --retry $stop_timeout \
+               --pidfile "${BOINC_PIDFILE}"
        eend $?
 }
 
 
 resume() {
-       for url in $(boinccmd --get_project_status | sed -n 's/\s*master URL: 
//p'); do
-               boinccmd --project ${url} resume
+       env_check || return 1
+
+       local password=""
+       local master_urls=( \
+               $("${BOINCCMD}" --get_project_status | \
+                 sed -n 's/\s*master URL: //p') \
+       )
+
+       if need_passwd_arg; then
+               password="--passwd \"$(cat "${RUNTIMEDIR}/gui_rpc_auth.cfg")\""
+       fi
+
+       for url in "${master_urls[@]}"; do
+               ebegin "Resuming $url"
+               start-stop-daemon --user "${USER}:${GROUP}" --quiet \
+                       --chdir "${RUNTIMEDIR}" --exec "${BOINCCMD}" \
+                       -- ${password} --project ${url} resume
+               eend $?
        done
 }
 
 
 suspend() {
-       for url in $(boinccmd --get_project_status | sed -n 's/\s*master URL: 
//p'); do
-               boinccmd --project ${url} suspend;
+       env_check || return 1
+
+       local password=""
+       local master_urls=( \
+               $("${BOINCCMD}" --get_project_status | \
+                 sed -n 's/\s*master URL: //p') \
+       )
+
+       if need_passwd_arg; then
+               password="--passwd \"$(cat "${RUNTIMEDIR}/gui_rpc_auth.cfg")\""
+       fi
+
+       for url in "${master_urls[@]}"; do
+               ebegin "Suspending $url"
+               start-stop-daemon --user "${USER}:${GROUP}" --quiet \
+                       --chdir "${RUNTIMEDIR}" --exec "${BOINCCMD}" \
+                       -- ${password} --project ${url} suspend
+               eend $?
        done
 }

Reply via email to