YARP
Yet Another Robot Platform
Terminator.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <yarp/os/Network.h>
8 #include <yarp/os/Port.h>
9 #include <yarp/os/Terminator.h>
10 #include <yarp/os/Vocab.h>
14 
15 #include <cstdio>
16 
17 
18 using namespace yarp::os::impl;
19 using namespace yarp::os;
20 
21 namespace {
22 YARP_OS_LOG_COMPONENT(TERMINATOR, "yarp.os.Terminator")
23 }
24 
25 
26 bool Terminator::terminateByName(const char* name)
27 {
28  if (name == nullptr) {
29  return false;
30  }
31 
32  std::string s(name);
33 
34  if (s.find("/quit") == std::string::npos) {
35  // name doesn't include /quit
36  // old mechanism won't work, let's try new
37  PortCommand pc('\0', "i");
38  NetworkBase::sendMessage(s, pc, true);
39  return true;
40  }
41 
42  if (name[0] != '/') {
43  s.clear();
44  s += "/";
45  s += name;
46  }
47 
48  Bottle cmd("quit");
49  Bottle reply;
51  if (!c.isValid()) {
52  yCError(TERMINATOR, "Terminator port not found");
53  return false;
54  }
55  ContactStyle style;
56  style.quiet = false;
57  style.carrier = "text_ack";
58  style.expectReply = true;
59  NetworkBase::write(c, cmd, reply, style);
60 
61  return true;
62 }
63 
64 #define TermineeHelper Port
65 #define HELPER(x) (*((TermineeHelper*)(x)))
66 
67 Terminee::Terminee(const char* name)
68 {
69  ok = false;
70  implementation = nullptr;
71  if (name == nullptr) {
72  quit = true;
73  yCError(TERMINATOR, "Terminator: Please supply a proper port name");
74  return;
75  }
76 
77  std::string s(name);
78  if (name[0] != '/') {
79  s.clear();
80  s += "/";
81  s += name;
82  }
83 
85  yCAssert(TERMINATOR, implementation != nullptr);
87  ok = helper.open(s);
88  if (!ok) {
89  quit = true;
90  yCError(TERMINATOR, "Kill port conflict: make sure you supply a distinct --name /PORTNAME");
91  } else {
92  quit = false;
93  start();
94  }
95 }
96 
98 {
100  quit = true;
101  helper.interrupt();
102 }
103 
105 {
107  if (!quit) {
108  Terminator::terminateByName(helper.getName().c_str());
109  }
110 
111  stop();
112 
113  if (implementation != nullptr) {
114  delete &HELPER(implementation);
115  }
116 }
117 
118 
120 {
122  while (!isStopping() && !quit) {
123  Bottle cmd;
124  Bottle reply;
125  bool ok = helper.read(cmd, true);
126  if (!ok) {
127  continue;
128  }
129  if (cmd.get(0).asString() == "quit") {
130  quit = true;
131  reply.addVocab32('o', 'k');
132  } else {
133  reply.addVocab32('h', 'u', 'h', '?');
134  }
135  helper.reply(reply);
136  }
137 }
138 
139 bool Terminee::waitQuit() const
140 {
141  // not yet implemented
142  return false;
143 }
144 
145 bool Terminee::mustQuit() const
146 {
147  return quit;
148 }
149 
150 
151 bool Terminee::isOk() const
152 {
153  return ok;
154 }
RandScalar * implementation(void *t)
Definition: RandnScalar.cpp:17
#define HELPER(x)
Definition: Terminator.cpp:65
#define TermineeHelper
Definition: Terminator.cpp:64
classes to handle graceful process termination.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:164
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
Preferences for how to communicate with a contact.
Definition: ContactStyle.h:24
bool quiet
Suppress all outputs and warnings.
Definition: ContactStyle.h:36
std::string carrier
Request that communication be made using a particular carrier.
Definition: ContactStyle.h:53
bool expectReply
Specify whether you expect a reply to a message.
Definition: ContactStyle.h:58
Represents how to reach a part of a YARP network.
Definition: Contact.h:36
bool isValid() const
Checks if a Contact is tagged as valid.
Definition: Contact.cpp:298
static Contact queryName(const std::string &name)
Find out information about a registered name.
Definition: Network.cpp:995
static int sendMessage(const std::string &port, yarp::os::PortWriter &writable, bool silent=false)
Just a reminder to sendMessage with temporary output parameter that will be discarded.
Definition: Network.cpp:1470
static bool write(const Contact &contact, PortWriter &cmd, PortReader &reply, bool admin=false, bool quiet=false, double timeout=-1)
Send a single command to a port and await a single response.
Definition: Network.cpp:1226
static bool terminateByName(const char *name)
Send a quit message to a specific socket port.
Definition: Terminator.cpp:26
void run() override
Main body of the new thread.
Definition: Terminator.cpp:119
Terminee(const char *name)
Constructor.
Definition: Terminator.cpp:67
virtual ~Terminee()
Destructor.
Definition: Terminator.cpp:104
bool isOk() const
Check whether the message mechanism is ok.
Definition: Terminator.cpp:151
bool mustQuit() const
Call this method to see whether a quit message has been received.
Definition: Terminator.cpp:145
void onStop() override
Call-back, called while halting the thread (before join).
Definition: Terminator.cpp:97
bool waitQuit() const
Call this method to wait for a quit message.
Definition: Terminator.cpp:139
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
Simple Readable and Writable object representing a command to a YARP port.
Definition: PortCommand.h:26
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCAssert(component, x)
Definition: LogComponent.h:169
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:35
The components from which ports and connections are built.
An interface to the operating system, including Port based communication.