The attached patch changes the allocation semantics of the cached Xrl
pointer to be per-client-instance rather than per-library-instance.
It does this by modifying the Xrl client stub generator to include a
named auto_ptr<Xrl> for each method in the Xrl client stub.
Sizes are for FreeBSD 7.2/amd64 with gcc 4.2.1. Hopefully it should give
others a feel for working with the code generator.
This probably doesn't fix the original race, but it may make it
easier to mitigate some other way, by giving us a handle on the cached
Xrls which are causing the problem, rather than letting them dangle in
the BSS segment. That, and it should fix the glaringly obvious memory
leakage, and non-reentrancy, caused by polluting a library with 'static
Xrl*' instances.
I've tested this briefly with the current SVN tree, just by running
a xorp_finder, call_xrl, and a xorp_rib. This exercises the reentrancy
of the XRL client stubs, because the Finder Client is instantiated once
for every XrlRouter. The RIB uses libfeaclient, which instantiates its
*own* XrlRouter instance (yes, you can have more than one per
process...) for getting interface updates from the FEA.
This patch does increase the code size of the stubs very slightly;
that's the trade-off. As we are no longer holding the cached 'static
Xrl*' in the BSS segment, it shrinks versus the code segment;
auto_ptr<T> doesn't use any additional data storage above the pointer
type, but we are now checking allocations and deallocations of Xrl for
the stubs.
When building with shared libraries, the template expansions for
auto_ptr are a lost opportunity for coalescing with the linker, although
this only wastes ~128 bytes per library (for auto_ptr<Xrl>::get() and
auto_ptr<Xrl>::reset()). Most of this seems to be NOP padding for cache
line alignment.
I'm still not 100% happy with how the XrlPFSender cache mechanism
works. Because we're holding a pointer somewhere, to something whose
lifecycle is managed somewhere else, there really isn't any other answer
than the one you've already suggested.
I'm not that happy about using ref_ptr<T> to do it, for much the
same reasons as I've already described earlier in this thread -- there
is no clean syntax for observing a ref_ptr vs Boost's shared_ptr/weak_ptr.
I'm not at all happy about using ref_ptr<T>&, because it is all too
easy to ignore its specific meaning and introduce problems. Certainly,
the only reason I did it in Spt, was because that class was already
using ref_ptr<T> internally to track nodes in a container.
Granted, this is code fairly deep down in the core of the tree,
which many developers would never need to touch directly, but that makes
it even more important to be careful.
In Thrift, the binary blobs themselves can be decoupled from where
they go. There is a potential chicken-and-egg problem if we support
multiple TProtocol types, where we would need to know the sender before
the stubs create the blob; if we just speak TBinaryProtocol to
everything, we don't have this problem, but it does mean we can't just
tell the XORP RPC endpoints 'speak JSON to this guy', 'speak XML-RPC to
this guy', 'speak AMQP to this guy' etc.
So the idea of caching the transport we'd prefer to transmit from,
is still one that bears further scrutiny, even in a re-spin. The
difference is, for maximum flexibility, Thrifted XRL stubs would
actually want to see XrlPFSender's equivalent upfront, before
XrlSender::send() is even called.
This is after scrutinizing libxipc even further this week, and
realizing most of what's there is to support asynchrony.
text data bss dec hex filename
156243 4560 56 160859 2745b libbgpxif.so
31757 1456 8 33221 81c5 libclimanagerxif.so
18387 1456 56 19899 4dbb libcliprocessorxif.so
26198 1680 56 27934 6d1e libcommonxif.so
26123 1760 56 27939 6d23 libcoordxif.so
19243 1376 8 20627 5093 libdatainxif.so
38481 1504 8 39993 9c39 libfeaclickxif.so
29171 1512 8 30691 77e3 libfeafibclientxif.so
18825 1320 8 20153 4eb9 libfeafibxif.so
61204 2400 56 63660 f8ac libfeafirewallxif.so
71143 1768 8 72919 11cd7 libfeaifmgrmirrorxif.so
15623 1272 8 16903 4207 libfeaifmgrreplicatorxif.so
150832 4136 56 155024 25d90 libfeaifmgrxif.so
16794 1360 8 18162 46f2 libfearawlinkclientxif.so
23561 1424 8 24993 61a1 libfearawlinkxif.so
18517 1424 8 19949 4ded libfearawpkt4clientxif.so
24473 1456 8 25937 6551 libfearawpkt4xif.so
19420 1456 8 20884 5194 libfearawpkt6clientxif.so
25376 1488 8 26872 68f8 libfearawpkt6xif.so
17594 1288 8 18890 49ca libfib2mribxif.so
24001 1608 56 25665 6441 libfinderclientxif.so
18569 1288 8 19865 4d99 libfindereventnotifierxif.so
15687 1272 8 16967 4247 libfindereventobserverxif.so
60566 2624 56 63246 f70e libfinderxif.so
66026 2656 56 68738 10c82 libftixif.so
24535 1448 8 25991 6587 libmfeaclientxif.so
60890 1928 56 62874 f59a libmfeaxif.so
21082 1384 8 22474 57ca libmld6igmpclientxif.so
72582 2216 56 74854 12466 libmld6igmpxif.so
107675 3400 56 111131 1b21b libospfv2xif.so
109056 3440 56 112552 1b7a8 libospfv3xif.so
387552 5144 56 392752 5fe30 libpimxif.so
17276 1312 8 18596 48a4 libpolicybackendxif.so
18938 1400 8 20346 4f7a libpolicyredist4xif.so
18938 1400 8 20346 4f7a libpolicyredist6xif.so
39396 1712 56 41164 a0cc libpolicyxif.so
16329 1304 8 17641 44e9 libprofileclientxif.so
24369 1600 56 26025 65a9 libprofilexif.so
20864 1384 8 22256 56f0 libredist4xif.so
20864 1384 8 22256 56f0 libredist6xif.so
28993 1680 56 30729 7809 libredisttransaction4xif.so
28993 1680 56 30729 7809 libredisttransaction6xif.so
20856 1384 8 22248 56e8 libribclientxif.so
129643 3752 56 133451 2094b libribxif.so
122275 3704 56 126035 1ec53 libripngxif.so
127945 3736 56 131737 20299 libripxif.so
20872 1360 8 22240 56e0 librtrmgrclientxif.so
71355 3008 56 74419 122b3 librtrmgrxif.so
28119 1704 56 29879 74b7 libsocket4userxif.so
49645 1832 56 51533 c94d libsocket4xif.so
28119 1704 56 29879 74b7 libsocket6userxif.so
45034 1808 56 46898 b732 libsocket6xif.so
59187 1672 8 60867 edc3 libstaticroutesxif.so
26859 1432 8 28299 6e8b libtestpeerxif.so
29075 1808 56 30939 78db libtestxif.so
28140 1600 8 29748 7434 libtestxrlsxif.so
56229 2528 56 58813 e5bd libvrrpxif.so
text data bss dec hex filename
153761 4536 456 158753 26c21 libbgpxif.so
30503 1432 120 32055 7d37 libclimanagerxif.so
17860 1432 64 19356 4b9c libcliprocessorxif.so
25560 1656 80 27296 6aa0 libcommonxif.so
25453 1736 80 27269 6a85 libcoordxif.so
18620 1352 40 20012 4e2c libdatainxif.so
36791 1480 168 38439 9627 libfeaclickxif.so
28467 1488 80 30035 7553 libfeafibclientxif.so
18117 1296 48 19461 4c05 libfeafibxif.so
60227 2376 176 62779 f53b libfeafirewallxif.so
68732 1744 336 70812 1149c libfeaifmgrmirrorxif.so
14981 1248 32 16261 3f85 libfeaifmgrreplicatorxif.so
147502 4112 512 152126 2523e libfeaifmgrxif.so
16267 1336 24 17627 44db libfearawlinkclientxif.so
22962 1400 56 24418 5f62 libfearawlinkxif.so
18022 1400 24 19446 4bf6 libfearawpkt4clientxif.so
23770 1432 56 25258 62aa libfearawpkt4xif.so
18925 1432 24 20381 4f9d libfearawpkt6clientxif.so
24809 1464 56 26329 66d9 libfearawpkt6xif.so
16886 1264 48 18198 4716 libfib2mribxif.so
23260 1584 88 24932 6164 libfinderclientxif.so
17799 1264 48 19111 4aa7 libfindereventnotifierxif.so
15047 1248 32 16327 3fc7 libfindereventobserverxif.so
59430 2600 160 62190 f2ee libfinderxif.so
64582 2632 184 67398 10746 libftixif.so
24083 1424 48 25555 63d3 libmfeaclientxif.so
59360 1904 280 61544 f068 libmfeaxif.so
20506 1360 48 21914 559a libmld6igmpclientxif.so
69988 2192 328 72508 11b3c libmld6igmpxif.so
105366 3376 344 109086 1aa1e libospfv2xif.so
106649 3416 352 110417 1af51 libospfv3xif.so
372963 5120 1840 379923 5cc13 libpimxif.so
16589 1288 40 17917 45fd libpolicybackendxif.so
18379 1376 32 19787 4d4b libpolicyredist4xif.so
18379 1376 32 19787 4d4b libpolicyredist6xif.so
38126 1688 176 39990 9c36 libpolicyxif.so
15722 1280 32 17034 428a libprofileclientxif.so
23568 1576 96 25240 6298 libprofilexif.so
20220 1360 48 21628 547c libredist4xif.so
20220 1360 48 21628 547c libredist6xif.so
28223 1656 96 29975 7517 libredisttransaction4xif.so
28223 1656 96 29975 7517 libredisttransaction6xif.so
20180 1360 48 21588 5454 libribclientxif.so
127737 3728 416 131881 20329 libribxif.so
120441 3680 360 124481 1e641 libripngxif.so
125995 3712 392 130099 1fc33 libripxif.so
20052 1336 56 21444 53c4 librtrmgrclientxif.so
69988 2984 184 73156 11dc4 librtrmgrxif.so
27404 1680 88 29172 71f4 libsocket4userxif.so
48393 1808 200 50401 c4e1 libsocket4xif.so
27404 1680 88 29172 71f4 libsocket6userxif.so
43895 1784 176 45855 b31f libsocket6xif.so
58097 1648 240 59985 ea51 libstaticroutesxif.so
25799 1408 96 27303 6aa7 libtestpeerxif.so
28323 1784 88 30195 75f3 libtestxif.so
27334 1576 72 28982 7136 libtestxrlsxif.so
55293 2504 152 57949 e25d libvrrpxif.so
Index: xrl/scripts/clnt-gen
===================================================================
--- xrl/scripts/clnt-gen (revision 11574)
+++ xrl/scripts/clnt-gen (working copy)
@@ -57,6 +57,7 @@
def implement_send_xrl(cls, method_no, method, ifqname):
cb_name = "%sCB" % (caps_cpp_classname(method.name()))
+ xrl_ptr_name = "ap_xrl_%s" % method.name()
atypes = ["\n\tconst char*\tdst_xrl_target_name"]
for a in method.args():
atypes.append("\n\tconst %s&\t%s" % (a.cpp_type(), a.name()))
@@ -64,12 +65,13 @@
s = "\nbool\n%s::send_%s(%s\n)\n{\n" \
% (cls, cpp_name(method.name()), csv(atypes))
- s += " static Xrl* x = NULL;\n"
+ s += " Xrl* x = %s.get();\n" % xrl_ptr_name
s += "\n"
s += " if (!x) {\n"
s += " x = new Xrl(dst_xrl_target_name, \"%s\");\n" % ifqname
for a in method.args():
s += " x->args().add(\"%s\", %s);\n" % (a.name(), a.name())
+ s += " %s.reset(x);\n" % xrl_ptr_name
s += " }\n"
s += "\n"
s += " x->set_target(dst_xrl_target_name);\n"
@@ -95,6 +97,11 @@
s += "\n%s);\n\n" % xorp_indent(1)
return s
+def declare_xrl_auto_ptr(method_name):
+ xrl_ptr_name = "ap_xrl_%s" % method_name
+ s = xorp_indent(1) + "auto_ptr<Xrl> %s;\n" % xrl_ptr_name
+ return s
+
def implement_unmarshall(cls, method_no, method):
nargs = []
@@ -163,6 +170,7 @@
#include "libxipc/xrl_error.hh"
#include "libxipc/xrl_sender.hh"
+#include <memory>
""" % (protect(hh_file), protect(hh_file), modulename)
return s
@@ -184,6 +192,12 @@
"""
for i in range(0, len(methods)):
s += declare_unmarshall(methods[i].name())
+
+ s += "private:\n"
+ s += " /* Declare cached Xrl pointers */\n"
+ for i in range(0, len(methods)):
+ s += declare_xrl_auto_ptr(methods[i].name())
+
s += "};\n"
return s
_______________________________________________
Xorp-hackers mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers