This service will be undergoing maintenance at 00:00 UTC, 2017-10-23 It is expected to last about 30 minutes
Bug 963224 - DOC: reword or clarify "suddenly disappears" in BindsTo documentation
DOC: reword or clarify "suddenly disappears" in BindsTo documentation
Status: CLOSED NOTABUG
Product: Fedora
Classification: Fedora
Component: systemd (Show other bugs)
18
Unspecified Unspecified
unspecified Severity unspecified
: ---
: ---
Assigned To: systemd-maint
Fedora Extras Quality Assurance
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2013-05-15 08:41 EDT by Nate Nephew
Modified: 2013-10-06 21:10 EDT (History)
9 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2013-10-06 21:10:35 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Nate Nephew 2013-05-15 08:41:30 EDT
Description of problem:
If a.service requires b.service and b.service enters a failed state, a.service is not stopped by systemd.

Version-Release number of selected component (if applicable):
systemd-197-1.fc18.2.x86_64

How reproducible:
100%

Steps to Reproduce:
1. Create b.service unit 
2. Create a.service unit with Requires=b.service
3. systemctl start a.service (which starts b.service). b.service ExecStart returns with status=1/FAILURE 
  
Actual results:
a.service starts without issue and Active: active (running)
b.service has failed and Active: active (exited)

Expected results:
a.service stops when b.service fails to start up

Additional info:
Based on documentation for systemd.unit, I believe this should work how I expect.  I have also tried the same thing with BindsTo rather than Requires.
Comment 1 Jóhann B. Guðmundsson 2013-05-15 09:22:11 EDT
Service A has to be bound to service B. and you need both if service a requires 
service b 

Basically something like in the [Unit] section of service A

Requires=b.service
BindTo=b.service
After=b.service ( or Before= ) 

And you will need to bind b.service to a.service if it's supposed to stop if a.service is stopped or fails for some reason.

Also note you always put the requirement or the binding in the unit that requires the other unit to work properly. 

So if unit A works just fine on it's own but unit B. requires unit A to run or work properly you never put the requirement ( or the binding ) for unit B in unit A
Comment 2 Michal Schmidt 2013-05-15 09:26:59 EDT
(In reply to comment #1)
> Service A has to be bound to service B. and you need both if service a
> requires service b

Umm, no, BindsTo is meant to be a stronger Requires. If adding an explicit "Requires" to an existing "BindsTo" dependency changes the behaviour, something is wrong.
Comment 3 Michal Schmidt 2013-05-15 09:28:41 EDT
Nate,
to make sure we're on the same page, would you please paste or attach the complete unit files for a.service and b.service?
Comment 4 Jóhann B. Guðmundsson 2013-05-15 09:58:47 EDT
(In reply to comment #2)
> (In reply to comment #1)
> > Service A has to be bound to service B. and you need both if service a
> > requires service b


You are right I got confused since he mentioned both but from his use case PartOf= might be sufficient

> 
> Umm, no, BindsTo is meant to be a stronger Requires. If adding an explicit
> "Requires" to an existing "BindsTo" dependency changes the behaviour,
> something is wrong.

BindsTo=
Requires=
RequiresOverridable=
Requisite=
PartOf=
Wants=


testa.service

[Unit]
Description=Test service A
Documentation=http://www.example.com
BindsTo=testb.service
Requires=testb.service
RequiresOverridable=testb.service
Requisite=testb.service
PartOf=testb.service
Wants=testb.service

testb.service

[Service]
ExecStart=/path/to/type simple daemon

[Unit]
Description=Test service B
Documentation=http://www.example.com

[Service]
ExecStart=/path/to/type simple daemon


There are no warning nor does systemd error out when defining all the relevant conf switches ( we really should fail to start a unit with invalid combination of configuration switches )  so what's the precedence order if you have all or combination of the following in the [Unit] sections as in do we order from weakest to strongest  ( making BindsTo= being what's eventually used ) or do we use the weakest ( making wants the what's eventually being used )?
Comment 5 Michal Schmidt 2013-05-15 10:17:12 EDT
(In reply to comment #4)
> There are no warning nor does systemd error out when defining all the
> relevant conf switches ( we really should fail to start a unit with invalid
> combination of configuration switches )

It's not invalid, just redundant.
Comment 6 Michal Schmidt 2013-05-15 10:20:24 EDT
Also, we are digressing from the original bug report.
Comment 7 Nate Nephew 2013-05-15 11:06:59 EDT
In my case, b.service is failing to start because the jar file is not available.

picaps-poller.service - PICAPS Poller
          Loaded: loaded (/etc/systemd/system/picaps-poller.service; static)
          Active: active (exited) (Result: exit-code) since Wed 2013-05-15 08:30:43 EDT; 2s ago
         Process: 12372 ExecStart=/bin/java -Xms${XMS} -Xmx${XMX} -DSYSTEM=POLLER -DResourceFactoryClass=com.dartcontainer.mdc.picaps.PicapsResourceFactory -Djava.awt.headless=true -Duser.dir=/dist/ -Dplant=${PLANT} -Dbuild=${POLLER_BUILD} -DPOLLER_STATISTICS=${POLLER_STATISTICS} -jar /dist/Picaps-${POLLER_BUILD}.jar com.dartcontainer.mdc.picaps.poller.PlantFloorPoller ${POLLER_ID} 0.0.0.0:0 127.0.0.1:${POLLER_IPPORT_PREFIX}${POLLER_ID} ${POLLER_INTERVAL} 0 (code=exited, status=1/FAILURE)
         Process: 12363 ExecStartPre=/dist/bin/startup-shutdown/prepare.sh $DELETE_CHECKPOINT (code=exited, status=0/SUCCESS)


Here are the unit files:


a.service

[Unit]
Description=PICAPS Poller XML-RPC
PartOf=picaps-all.target
Requires=picaps-poller.service
After=mysqld.service
After=picaps-display.service
After=picaps-persister.service

[Service]
Type=simple
WorkingDirectory=/dist/bin
EnvironmentFile=/etc/sysconfig/picaps
EnvironmentFile=/etc/sysconfig/picaps-poller
ExecStartPre=/dist/bin/startup-shutdown/prepare.sh $DELETE_CHECKPOINT
ExecStartPre=/bin/setserial $POLLER_SERIALDEV low_latency
ExecStart=/bin/python xmlrpc-serial-port.py $POLLER_SERIALDEV 127.0.0.1 ${POLLER_IPPORT_PREFIX}${POLLER_ID}
RemainAfterExit=yes
TimeoutStopSec=0

[Install]
WantedBy=picaps-all.target





b.service

[Unit]
Description=PICAPS Poller
PartOf=picaps-all.target
After=mysqld.service
After=picaps-display.service
After=picaps-persister.service
After=picaps-poller-xmlrpc.service

[Service]
Type=simple
WorkingDirectory=/dist/bin
EnvironmentFile=/etc/sysconfig/picaps
EnvironmentFile=/etc/sysconfig/picaps-poller
ExecStartPre=/dist/bin/startup-shutdown/prepare.sh $DELETE_CHECKPOINT
ExecStart=/bin/java \
            -Xms${XMS} \
            -Xmx${XMX} \
            -DSYSTEM=POLLER \
            -DResourceFactoryClass=com.dartcontainer.mdc.picaps.PicapsResourceFactory \
            -Djava.awt.headless=true \
            -Duser.dir=/dist/ \
            -Dplant=${PLANT} \
            -Dbuild=${POLLER_BUILD} \
            -DPOLLER_STATISTICS=${POLLER_STATISTICS} \
            -jar /dist/Picaps-${POLLER_BUILD}.jar \
            com.dartcontainer.mdc.picaps.poller.PlantFloorPoller \
            ${POLLER_ID} 0.0.0.0:0 127.0.0.1:${POLLER_IPPORT_PREFIX}${POLLER_ID} ${POLLER_INTERVAL} 0

RemainAfterExit=yes
TimeoutStopSec=0

[Install]
WantedBy=picaps-all.target
Comment 8 Michal Schmidt 2013-05-15 11:32:52 EDT
(In reply to comment #7)

OK, here's my take on it:

> picaps-poller.service - PICAPS Poller
>           Loaded: loaded (/etc/systemd/system/picaps-poller.service; static)
>           Active: active (exited) (Result: exit-code) since Wed 2013-05-15
> 08:30:43 EDT; 2s ago

The service's state is "active". From systemd's point of view, the requirement dependency is thus fulfilled.

Do you really need that "RemainAfterExit=yes"? What happens if you remove it?

> [Service]
> Type=simple

One disadvantage of "Type=simple" is that they do not really ever fail to activate. (I am simplifying a little bit by ignoring ExecStartPre here, which does cause the service to spend some time in the 'activating' state, but that's not interesting for the point I'm trying to make.)

"Type=simple" services go from an inactive state straight into running. If the ExecStart command fails, it's therefore treated in the same way as a failure of a service that's been running for a while. I would not expect this kind of a failure to propagate to services that Require this service and cause them to stop. Though I would expect it for services that have BindsTo on this service.
Comment 9 Nate Nephew 2013-05-15 13:23:42 EDT
Everything seems to work as intended using "BindsTo="  WITHOUT "RemainAfterExit=yes".

Your explanation of "activation" makes sense but this isn't really what I expected from reading the documentation for systemd.unit which says:

"BindsTo=

Configures requirement dependencies, very similar in style to Requires=, however in addition to this behavior it also declares that this unit is stopped when any of the units listed suddenly disappears."

I guess I didn't this to qualify as "suddenly disappears" without systemd's involvement.

Either way, I suppose this is working how I need it to and it sounds like the way it is intended to work.  I'm not sure if the documentation could be cleared up in any way or if I was just reading it from the wrong angle.

Thanks!
Comment 10 Michal Schmidt 2013-05-15 13:48:12 EDT
Yes, the documentation could be clarified.
Comment 11 Nate Nephew 2013-05-15 14:02:17 EDT
Perhaps a look at explaining "activation" in the Requires= documentation as well?
Comment 12 Zbigniew Jędrzejewski-Szmek 2013-06-12 14:10:35 EDT
(In reply to Nate Nephew from comment #9)
> Everything seems to work as intended using "BindsTo="  WITHOUT
> "RemainAfterExit=yes".
> 
> Your explanation of "activation" makes sense but this isn't really what I
> expected from reading the documentation for systemd.unit which says:
> 
> "BindsTo=
> 
> Configures requirement dependencies, very similar in style to Requires=,
> however in addition to this behavior it also declares that this unit is
> stopped when any of the units listed suddenly disappears."
> 
> I guess I didn't this to qualify as "suddenly disappears" without systemd's
> involvement.

It's already clarified in the next sentence:

       BindsTo=
           Configures requirement dependencies, very similar in style to
           Requires=, however in addition to this behavior it also declares
           that this unit is stopped when any of the units listed suddenly
           disappears. Units can suddenly, unexpectedly disappear if a
           service terminates on its own choice, a device is unplugged or a
           mount point unmounted without involvement of systemd.

It's been this way since 2010.
Comment 13 Zbigniew Jędrzejewski-Szmek 2013-10-06 21:10:35 EDT
If anyone has a concrete suggestion what should be fixed, we can do that. But since there doesn't seem to be anything actually wrong, I'm closing this.

Note You need to log in before you can comment on or make changes to this bug.