Ben Greear wrote:
XRL caches a pointer to the resolved_sender, but when something
deletes a sender, it doesn't appear to clean up any existing XRLs.
This leads to a crash on a highly loaded system (where senders must be
timing out
or something like that).
Looks like a good place for smart pointers. I'm going to attempt that
unless
someone has another idea...
The attached patch seems to fix the problem.
Thanks,
Ben
--
Ben Greear <[email protected]>
Candela Technologies Inc http://www.candelatech.com
diff --git a/libxipc/xrl.cc b/libxipc/xrl.cc
index 187c7b1..5de3e1d 100644
--- a/libxipc/xrl.cc
+++ b/libxipc/xrl.cc
@@ -76,7 +76,7 @@ Xrl::Xrl(const string& protocol,
const XrlArgs& args)
: _protocol(protocol), _target(protocol_target), _command(command),
_args(args), _sna_atom(NULL), _packed_bytes(0), _argp(&_args),
- _to_finder(-1), _resolved(false), _resolved_sender(NULL)
+ _to_finder(-1), _resolved(false)
{
}
@@ -85,7 +85,7 @@ Xrl::Xrl(const string& target,
const XrlArgs& args)
: _protocol(_finder_protocol), _target(target), _command(command),
_args(args), _sna_atom(NULL), _packed_bytes(0), _argp(&_args),
- _to_finder(-1), _resolved(false), _resolved_sender(NULL)
+ _to_finder(-1), _resolved(false)
{
}
@@ -94,7 +94,7 @@ Xrl::Xrl(const string& protocol,
const string& command)
: _protocol(protocol), _target(protocol_target), _command(command),
_sna_atom(NULL), _packed_bytes(0), _argp(&_args), _to_finder(-1),
- _resolved(false), _resolved_sender(NULL)
+ _resolved(false)
{
}
@@ -102,7 +102,7 @@ Xrl::Xrl(const string& target,
const string& command)
: _protocol(_finder_protocol), _target(target), _command(command),
_sna_atom(NULL), _packed_bytes(0), _argp(&_args), _to_finder(-1),
- _resolved(false), _resolved_sender(NULL)
+ _resolved(false)
{
}
@@ -110,13 +110,13 @@ Xrl::Xrl(const char* target,
const char* command)
: _protocol(_finder_protocol), _target(target), _command(command),
_sna_atom(NULL), _packed_bytes(0), _argp(&_args), _to_finder(-1),
- _resolved(false), _resolved_sender(NULL)
+ _resolved(false)
{
}
Xrl::Xrl(const char* c_str) throw (InvalidString)
: _sna_atom(NULL), _packed_bytes(0), _argp(&_args),
- _to_finder(-1), _resolved(false), _resolved_sender(NULL)
+ _to_finder(-1), _resolved(false)
{
if (0 == c_str)
xorp_throw0(InvalidString);
@@ -136,7 +136,7 @@ Xrl::Xrl(const char* c_str) throw (InvalidString)
Xrl::Xrl()
: _sna_atom(0), _packed_bytes(0), _argp(&_args), _to_finder(-1),
- _resolved(false), _resolved_sender(NULL)
+ _resolved(false)
{
}
@@ -340,3 +340,15 @@ Xrl::clear_cache()
delete _sna_atom;
_sna_atom = NULL;
}
+
+ref_ptr<XrlPFSender> Xrl::resolved_sender_ref() const {
+ return _resolved_sender;
+}
+
+void Xrl::set_resolved_sender_ref(ref_ptr<XrlPFSender>& s) const {
+ _resolved_sender = s;
+}
+
+void Xrl::set_resolved_sender_ptr(XrlPFSender* s) const {
+ _resolved_sender = s;
+}
diff --git a/libxipc/xrl.hh b/libxipc/xrl.hh
index bb8052e..2eec2b6 100644
--- a/libxipc/xrl.hh
+++ b/libxipc/xrl.hh
@@ -30,8 +30,8 @@
#include "xrl_atom.hh"
#include "xrl_args.hh"
#include "xrl_tokens.hh"
-
-class XrlPFSender;
+#include "libxorp/ref_ptr.hh"
+#include "xrl_pf.hh" // Needed for ref_ptr instantiation of XrlPFSender
/**
* XORP IPC request.
@@ -169,8 +169,9 @@ public:
bool resolved() const { return _resolved; }
void set_resolved(bool r) const { _resolved = r; }
- XrlPFSender *resolved_sender() const { return _resolved_sender; }
- void set_resolved_sender(XrlPFSender *s) const { _resolved_sender = s; }
+ ref_ptr<XrlPFSender> resolved_sender_ref() const;
+ void set_resolved_sender_ref(ref_ptr<XrlPFSender>& s) const;
+ void set_resolved_sender_ptr(XrlPFSender* s) const;
void set_target(const char* target);
@@ -194,7 +195,7 @@ private:
mutable XrlArgs* _argp; // XXX shouldn't be mutable
mutable int _to_finder;
mutable bool _resolved; // XXX ditto
- mutable XrlPFSender* _resolved_sender; // XXX ditto
+ mutable ref_ptr<XrlPFSender> _resolved_sender; // XXX ditto
static const string _finder_protocol;
};
diff --git a/libxipc/xrl_pf.hh b/libxipc/xrl_pf.hh
index b185ee5..ae34e36 100644
--- a/libxipc/xrl_pf.hh
+++ b/libxipc/xrl_pf.hh
@@ -108,6 +108,7 @@ public:
const string& address() const { return _address; }
EventLoop& eventloop() const { return _eventloop; }
+ virtual void set_address(const char* a) { _address = a; }
private:
XrlPFSender(const XrlPFSender&); // Not implemented
diff --git a/libxipc/xrl_pf_factory.cc b/libxipc/xrl_pf_factory.cc
index 01cb230..9cd57f4 100644
--- a/libxipc/xrl_pf_factory.cc
+++ b/libxipc/xrl_pf_factory.cc
@@ -41,13 +41,14 @@
// real cost, unlike InProc and SUDP, so we maintain a cache of
// STCP senders with one per sender destination address.
-XrlPFSender*
+ref_ptr<XrlPFSender>
XrlPFSenderFactory::create_sender(EventLoop& eventloop,
const char* protocol,
const char* address)
{
debug_msg("instantiating sender pf = \"%s\", addr = \"%s\"\n",
protocol, address);
+ ref_ptr<XrlPFSender> rv;
try {
#if 0
if (strcmp(XrlPFSUDPSender::protocol_name(), protocol) == 0) {
@@ -55,7 +56,8 @@ XrlPFSenderFactory::create_sender(EventLoop& eventloop,
} else
#endif
if (strcmp(XrlPFSTCPSender::protocol_name(), protocol) == 0) {
- return new XrlPFSTCPSender(eventloop, address);
+ rv = new XrlPFSTCPSender(eventloop, address);
+ return rv;
}
#if 0
else if (strcmp(XrlPFInProcSender::protocol_name(), protocol) == 0) {
@@ -64,15 +66,17 @@ XrlPFSenderFactory::create_sender(EventLoop& eventloop,
return new XrlPFKillSender(eventloop, address);
} else
#endif
- if (strcmp(XrlPFUNIXSender::protocol_name(), protocol) == 0)
- return new XrlPFUNIXSender(eventloop, address);
+ if (strcmp(XrlPFUNIXSender::protocol_name(), protocol) == 0) {
+ rv = new XrlPFUNIXSender(eventloop, address);
+ return rv;
+ }
} catch (XorpException& e) {
XLOG_ERROR("XrlPFSenderFactory::create failed: %s\n", e.str().c_str());
}
- return 0;
+ return rv;
}
-XrlPFSender*
+ref_ptr<XrlPFSender>
XrlPFSenderFactory::create_sender(EventLoop& eventloop,
const char* protocol_colon_address)
{
@@ -80,7 +84,8 @@ XrlPFSenderFactory::create_sender(EventLoop& eventloop,
if (colon == 0) {
debug_msg("No colon in supposedly colon separated <protocol><address>"
"combination\n\t\"%s\".\n", protocol_colon_address);
- return 0;
+ ref_ptr<XrlPFSender> rv;
+ return rv;
}
string protocol(protocol_colon_address, colon - protocol_colon_address);
@@ -88,12 +93,12 @@ XrlPFSenderFactory::create_sender(EventLoop& eventloop,
}
void
-XrlPFSenderFactory::destroy_sender(XrlPFSender* s)
+XrlPFSenderFactory::destroy_sender(ref_ptr<XrlPFSender>& s)
{
debug_msg("destroying sender pf = \"%s\", addr = \"%s\"\n",
s->protocol(), s->address().c_str());
-
- delete s;
+ s->set_address("__DESTROYED__"); // for debugging.
+ // Ref-ptrs should clean themselves up..don't really need to do anything here.
}
void
diff --git a/libxipc/xrl_pf_factory.hh b/libxipc/xrl_pf_factory.hh
index 1b877db..41b737d 100644
--- a/libxipc/xrl_pf_factory.hh
+++ b/libxipc/xrl_pf_factory.hh
@@ -32,14 +32,14 @@ public:
static void startup();
static void shutdown();
- static XrlPFSender* create_sender(EventLoop& eventloop,
+ static ref_ptr<XrlPFSender> create_sender(EventLoop& eventloop,
const char* proto_colon_addr);
- static XrlPFSender* create_sender(EventLoop& e,
+ static ref_ptr<XrlPFSender> create_sender(EventLoop& e,
const char* protocol,
const char* address);
- static void destroy_sender(XrlPFSender* s);
+ static void destroy_sender(ref_ptr<XrlPFSender>& s);
};
#endif // __LIBXIPC_XRL_PF_FACTORY_HH__
diff --git a/libxipc/xrl_router.cc b/libxipc/xrl_router.cc
index 500c2ad..5f621c6 100644
--- a/libxipc/xrl_router.cc
+++ b/libxipc/xrl_router.cc
@@ -375,7 +375,7 @@ XrlRouter::add_handler(const string& cmd, const XrlRecvCallback& rcb)
void
XrlRouter::send_callback(const XrlError& e,
XrlArgs* reply,
- XrlPFSender* /* s */,
+ XrlPFSender* /* s */, // Don't use, should be a ref-ptr if it is ever used.
XrlCallback user_callback)
{
user_callback->dispatch(e, reply);
@@ -388,8 +388,8 @@ XrlRouter::send_resolved(const Xrl& xrl,
bool direct_call)
{
try {
- XrlPFSender* s = get_sender(xrl, const_cast<FinderDBEntry*>(dbe));
- if (s == 0) {
+ ref_ptr<XrlPFSender> s = get_sender(xrl, const_cast<FinderDBEntry*>(dbe));
+ if (!s.get()) {
// Notify Finder client that result was bad.
_fc->uncache_result(dbe);
@@ -399,10 +399,13 @@ XrlRouter::send_resolved(const Xrl& xrl,
const Xrl& x = dbe->xrls().front();
x.set_args(xrl);
- if (s) {
+ if (s.get()) {
trace_xrl("Sending ", x);
+ // NOTE: using s.get below breaks ref counting, but can't figure out WTF the
+ // callback template magic is to make it work with a ref-ptr. Either way, it appears
+ // the ptr may not be used anyway (it's not in send_callback, for instance)
return s->send(x, direct_call,
- callback(this, &XrlRouter::send_callback, s, cb));
+ callback(this, &XrlRouter::send_callback, s.get(), cb));
}
cb->dispatch(XrlError(SEND_FAILED, "sender not instantiated"), 0);
} catch (const InvalidString&) {
@@ -411,28 +414,34 @@ XrlRouter::send_resolved(const Xrl& xrl,
return false;
}
-XrlPFSender*
+ref_ptr<XrlPFSender>
XrlRouter::get_sender(const Xrl& xrl, FinderDBEntry* dbe)
{
const Xrl& x = dbe->xrls().front();
- XrlPFSender* s = NULL;
+ ref_ptr<XrlPFSender> s;
// Use the cache pointer to the sender.
if (xrl.resolved()) {
- s = xrl.resolved_sender();
+ s = xrl.resolved_sender_ref();
if (s->alive())
return s;
- XLOG_ASSERT(s->protocol() == x.protocol());
- XLOG_ASSERT(s->address() == x.target());
+ if (strcmp(s->protocol(), x.protocol().c_str()) != 0) {
+ XLOG_WARNING("ERROR: x->protocol: %s doesn't match x.protocol: %s\n",
+ s->protocol(), x.protocol().c_str());
+ }
+ if (s->address() != x.target()) {
+ XLOG_WARNING("ERROR: s->address: %s doesn't match x.target: %s\n",
+ s->address().c_str(), x.target().c_str());
+ }
xrl.set_resolved(false);
- xrl.set_resolved_sender(NULL);
+ xrl.set_resolved_sender_ptr(NULL);
}
// Find a new sender.
- for (list<XrlPFSender*>::iterator i = _senders.begin();
+ for (list<ref_ptr<XrlPFSender> >::iterator i = _senders.begin();
i != _senders.end(); ++i) {
s = *i;
@@ -441,7 +450,7 @@ XrlRouter::get_sender(const Xrl& xrl, FinderDBEntry* dbe)
if (s->alive()) {
xrl.set_resolved(true);
- xrl.set_resolved_sender(s);
+ xrl.set_resolved_sender_ref(s);
return s;
}
@@ -461,7 +470,7 @@ XrlRouter::get_sender(const Xrl& xrl, FinderDBEntry* dbe)
s = XrlPFSenderFactory::create_sender(_e, x.protocol().c_str(),
x.target().c_str());
- if (s)
+ if (s.get())
break;
XLOG_ERROR("Could not create XrlPFSender for protocol = \"%s\" "
@@ -470,8 +479,8 @@ XrlRouter::get_sender(const Xrl& xrl, FinderDBEntry* dbe)
dbe->pop_front();
}
- if (!s)
- return NULL;
+ if (!s.get())
+ return s;
const Xrl& front = dbe->xrls().front();
@@ -505,7 +514,7 @@ XrlRouter::resolve_callback(const XrlError& e,
if (e == XrlError::OKAY()) {
const Xrl& xrl = ds->xrl();
xrl.set_resolved(false);
- xrl.set_resolved_sender(NULL);
+ xrl.set_resolved_sender_ptr(NULL);
if (send_resolved(xrl, dbe, ds->cb(), false) == false) {
// We tried to force sender to send xrl and it declined the
// opportunity. This should only happen when it's out of buffer
@@ -712,30 +721,32 @@ XrlRouter::finder_ready_event(const string& tgt_name)
void
XrlRouter::batch_start(const string& target)
{
- XrlPFSender& sender = get_sender(target);
-
- sender.batch_start();
+ ref_ptr<XrlPFSender> sender = get_sender(target);
+ if (sender.get()) {
+ sender->batch_start();
+ }
}
void
XrlRouter::batch_stop(const string& target)
{
- XrlPFSender& sender = get_sender(target);
-
- sender.batch_stop();
+ ref_ptr<XrlPFSender> sender = get_sender(target);
+ if (sender.get()) {
+ sender->batch_stop();
+ }
}
-XrlPFSender&
+ref_ptr<XrlPFSender>
XrlRouter::get_sender(const string& target)
{
- XrlPFSender* s = 0;
+ ref_ptr<XrlPFSender> s;
SENDERS::iterator i = _senders2.find(target);
XLOG_ASSERT(i != _senders2.end());
s = i->second;
- return *s;
+ return s;
}
string XrlRouter::toString() const {
diff --git a/libxipc/xrl_router.hh b/libxipc/xrl_router.hh
index 29ef12a..7af43b6 100644
--- a/libxipc/xrl_router.hh
+++ b/libxipc/xrl_router.hh
@@ -195,7 +195,7 @@ protected:
*/
void send_callback(const XrlError& e,
XrlArgs* reply,
- XrlPFSender* sender,
+ XrlPFSender* sender, // un-used, should be ref-ptr if we ever actually use this.
XrlCallback user_callback);
/**
@@ -213,8 +213,8 @@ protected:
uint16_t finder_port);
private:
- XrlPFSender& get_sender(const string& target);
- XrlPFSender* get_sender(const Xrl& xrl, FinderDBEntry *dbe);
+ ref_ptr<XrlPFSender> get_sender(const string& target);
+ ref_ptr<XrlPFSender> get_sender(const Xrl& xrl, FinderDBEntry *dbe);
protected:
EventLoop& _e;
@@ -226,13 +226,13 @@ protected:
list<XrlPFListener*> _listeners; // listeners
list<XrlRouterDispatchState*> _dsl; // dispatch state
- list<XrlPFSender*> _senders; // active senders
+ list<ref_ptr<XrlPFSender> > _senders; // active senders
static uint32_t _icnt; // instance count
private:
typedef map<string, XI*> XIM;
- typedef map<string, XrlPFSender*> SENDERS;
+ typedef map<string, ref_ptr<XrlPFSender> > SENDERS;
mutable XIM _xi_cache;
SENDERS _senders2;
_______________________________________________
Xorp-hackers mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers