[systemd-devel] Using *.path units without races?

Uwe Geuder systemd-devel-ugeuder at snkmail.com
Wed Mar 18 22:20:53 UTC 2020


Hi!

On Tue, 17 Mar 2020 at 23:52, Michael Chapman wrote:
>
> On Wed, 18 Mar 2020, Uwe Geuder wrote:
> > Hi!
> >
> > I have wondered for a while how I can use *.path units without (too bad)
> > races.
> >
> > Since
> > https://github.com/systemd/systemd/pull/13509/commits/06582e42de65a61d0238a18720a12b6353edb7cd
> > the behaviour has been become much clearer, but I must admit I still
> > don't get it.
>
> That commit does look incomplete to me.
>
> As a quick test, are you able to try out the patch below? This makes
> systemd always check the filesystem when the service stops, rather than
> just relying on the (as of that commit nonexistent) inotify event.
...
> diff --git a/src/core/path.c b/src/core/path.c
> index cb75d778af..a513df97b2 100644
> --- a/src/core/path.c
> +++ b/src/core/path.c
> @@ -759,11 +759,7 @@ static void path_trigger_notify(Unit *u, Unit *other) 
> {
>          if (p->state == PATH_RUNNING &&
>              UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
>                  log_unit_debug(UNIT(p), "Got notified about unit deactivation.");
> -
> -                /* Hmm, so inotify was triggered since the
> -                 * last activation, so I guess we need to
> -                 * recheck what is going on. */
> -                path_enter_waiting(p, false, p->inotify_triggered);
> +                path_enter_waiting(p, false, true);
>          }
>  }
> 

Thanks a lot Michael for this quick patch. The patch seems to have
suffered a formatting accident in the mail. However, your intent to
change the 3rd agument of that function call is pretty clear.

I built that change and quickly tested it. It seems to work fine!

Please note that I have not yet done any wider (regression) testing and
my understanding of the code base is not good.

I can share my test code

----- test.path -----
[Unit]
Description=%n testing racyness of path

[Path]
DirectoryNotEmpty=/tmp/systemd-path-test/
MakeDirectory=true


----- test.service -----
[Unit]
Description=%n testing racyness of path

[Service]
ExecStart=%h/try/systemd/test.sh


----- test.sh -----
#!/bin/sh -eu
# Usage: Expects to find <number>.sleep files in ${testdir}

echo "${0} starting"
testdir=/tmp/systemd-path-test/

exit_handler() {
  echo "${0} exiting"
}
trap exit_handler EXIT

# assume good faith, don't worry about dotfiles or
# pathologic filenames...
files=$(ls "${testdir}/")
if [ -z "${files}" ] ; then
  echo "No files found"
  exit
else
  echo "Found ${files}"
fi

for f in ${files} ; do
  if [ -e "${testdir}/${f}" ] ; then
      rm -f "${testdir}/${f}"
  else
    echo "Race: ${f} has disappeared"
  fi
  case "${f}" in
    *.sleep) # don't worry about non-numeric...
      s=$(basename "${f}" .sleep)
      echo "sleeping ${s}"
      sleep "${s}"
      ;;
  esac
done

------

Test case:

touch /tmp/systemd-path-test/5.sleep ; sleep 2 ; \
  touch /tmp/systemd-path-test/6.sleep ; sleep 5 ; \
  touch /tmp/systemd-path-test/0.5.sleep

(all 5 commands in one go)

As expected the service gets now invoked 3 times. Without your patch the
second touch command/file is missed and only "handled" together with the
third touch command/file.


Regards,

Uwe

Uwe Geuder
Neuro Event Labs Oy
Tampere, Finland
uwe.gxuder at neuroeventlabs.com (bot check: fix 1 obvious typo)


More information about the systemd-devel mailing list