Control: retitle -1 emacsen-addon package installation may never comes to an end
Control: severity -1 critical
Control: affects -1 = emacsen-common, elpa-company, elpa-js2-mode, 
elpa-markdown-mode, elpa-systemd, elpa-yasnippet


This bug report is about the failed error handling in installing emacsen-addons 
like *elpa-markdown-mode* or
*elpa-yasnippet*, et. al..

Especially all addons using this code fragment in there installer.

````
${FLAVOR} -q -batch -l package \
--eval "(add-to-list 'package-directory-list \"$src_dir\")" \
-f package-initialize -f batch-byte-compile *.el > Install.log 2>&1
```

In addition **all** addons relying on `emacs --batch` could be affected by this 
bug.

What is going wrong?
--------------------

The code fragment relies on the following assumption:

**Emacs in batch mode will terminate and not getting stuck**

Why is this assumption not valid – please consult the bug #886153.
Here is described hot a stale  emacs lock related to *anything-el* make emacs 
--batch never terminating.
→ https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=886153

As a serious side effect all error messages are buried in „Install.log“ and 
will not become visible until emacs
terminates – which in may case never happened.


Why is this a critical and security related problems
----------------------------------------------------

The problematic code fragment is invoked e.g. by `apt-get dist-upgrade` or 
`dpkg --configure -a`.
These tasks will also got stuck without any reason displayed on the console.

So `apt-get dist-upgrade` got broken and it is likely that the user terminates 
`apt-get` via kill (or simply reboot the
machine).

In this case he will be trapped in the pit, that he can't install any package 
without fixing the  „broken“ installation
of the emacsen-addon package via `dpkg --configure -a`.

This is also the case now for security related updates.

Affected Packages
------------------

I found the problematic code on my system in the 
`/usr/lib/emacsen-common/packages/install` files for

- elpa-company
- elpa-js2-mode
- elpa-markdown-mode
- elpa-systemd
- elpa-yasnippet

A „code review“ of other packages will surely result in some more defective 
packages.

How can this problem mitigated or fixed?
----------------------------------------

- A fix of bug #886153 would remove the trigger for the actual occurrence of 
this problem. But what is with the next
  defect in an emacs addon (or user stuff) breaking the batch processing again?
- A fix of of emacs concerning the `--batch` functionality – but this is maybe 
not in scope.
  See 
https://www.gnu.org/software/emacs/manual/html_node/emacs/Initial-Options.html#Initial-Options
  > „Functions that normally read keyboard input from the minibuffer take their 
input from the terminal's standard
  > input stream (stdin) instead.“
- Implement the assumption „emacs in batch mode will terminate and not getting 
stuck“ in a wrapper script. See below for
  a code outline.

What else is wrong with this emacsen addon installers.
------------------------------------------------------

It is may only a single line, but is is copied and paste between several 
packages including the minor flaw that (see
`man emacs`) it should be `--batch` with a **double** hyphen.

Here a simple wrapper script would help to :
- avoid copy and paste errors
- simplify the fix of this bug
- simple reuse


Code outline for an emacs batch wrapper
----------------------------------------

Assume a bash script *emacs_batch* replacing the `-q --batch` options.
It should take as 1st option the emacs flavour (e.g. emacs25) and pass trough 
all other options except `-q`,
`--no-init-file` (alias to `-q`)  and `--batch`.

The emacs call could be implemented in this way:

    ```
    declare -r catchFile=$(mktemp)              # create temporary file for 
output
    trap rm --force ${catchFile}                #   and ensure cleanup
    ${FLAVOUR} --batch "${cmdlineOptions[@]}" &>"${catchFile}" & # fork
    declare -i emacsPid=$!                      # and remember
    sleep ${emacsTimeOut} &                     # fork timeout watch
    declare -i sleepPid=$!                      # and remember
    wait -n ${emacsPid} ${sleepPid}             # -n  → wait for the next 
ending job
    declare -r rc=$?                            # don't forget the exit code
    if ! $(kill ${sleepPid})
    then                                        # oops run in timeout
       … add error handling here
    else                                        # emacs terminates without 
timeout
       cat ${catchFile}                         # forward console output
       exit ${rc}                               # rc is originating from emacs
    fi
    ```

Note: `--batch` implies `-q`
(→ 
https://www.gnu.org/software/emacs/manual/html_node/emacs/Initial-Options.html#Initial-Options)

Reply via email to