{"id":4696,"date":"2024-12-29T02:22:07","date_gmt":"2024-12-29T09:22:07","guid":{"rendered":"http:\/\/www.sheer.us\/weblogs\/?p=4696"},"modified":"2024-12-29T02:32:48","modified_gmt":"2024-12-29T09:32:48","slug":"avoiding-ref-leaks-in-perl-callback-code","status":"publish","type":"post","link":"http:\/\/www.sheer.us\/weblogs\/programming\/perl\/avoiding-ref-leaks-in-perl-callback-code","title":{"rendered":"Avoiding ref leaks in perl callback code"},"content":{"rendered":"<p>So, one of the big problems I&#8217;m having with kt3 is memory leaks. This is probably no surprise to anyone who has done XS programming before. <\/p>\n<p>I found one particularly pernicious one by using Devel::Leak.. this is in the log handler. <\/p>\n<p>Originally I had this, which I&#8217;m fairly sure I got from the internet somewhere:<\/p>\n<p><code><br \/>\nstatic void _kt_log_callback(int iLogLevel, char *log_subsystem, char *msg)<br \/>\n{<br \/>\n        dTHX;<br \/>\n        dSP;<\/p>\n<p>        HV *rv = newHV();<br \/>\n        sv_2mortal((SV *)rv);<\/p>\n<p>        hv_store(rv, \"loglevel\", 8, newSViv(iLogLevel),0);<br \/>\n        hv_store(rv, \"message\", 7, newSVpv(msg, strnlen(msg, KT_LOGBUFSIZE)),0);<br \/>\n        hv_store(rv, \"system\", 6, newSVpv(log_subsystem, strnlen(log_subsystem,32)),0);<\/p>\n<p>        PUSHMARK(SP);<br \/>\n        XPUSHs(newRV_noinc((SV *)rv));<br \/>\n        PUTBACK;<\/p>\n<p>        call_pv(\"KittenTrader::KittenBrain::Log\", G_DISCARD);<br \/>\n}<br \/>\n<\/code><\/p>\n<p>This worked well enough &#8211; it created a hash ref and passed it to the function &#8211; but the hash ref kept leaking. <\/p>\n<p>Eventually &#8211; after much digging through the documentation &#8211; I figured out that what I needed to do on the XPUSHs was this:<\/p>\n<p><code><br \/>\n        XPUSHs(sv_2mortal(newRV((SV *)rv)));<br \/>\n<\/code><\/p>\n<p>If anyone is curious how I debugged.. I used this relatively simple function to invoke the callback:<\/p>\n<p><code><br \/>\nmy $count = Devel::Leak::NoteSV($handle);<br \/>\nfor($i=0;$i<1000;$i++) {\n        KittenTrader::KittenBrain::testLog(4, \"THIS IS A MESSAGE\");\n}\n\nmy $count2 = Devel::Leak::NoteSV($handle);\n\nDevel::Leak::CheckSV($handle);\n\nprint \"Count: $count\\n\";\nprint \"Count2: $count2\\n\";\n<\/code><\/p>\n<p>This gave me a count of SVs, which I could clearly see my leaking SVs in.<\/p>\n<p>Then  I added returns everywhere along the path until I could isolate the leaking SV to a few lines of code. In particular I could definitely see that as soon as I created the hash, I was leaking a SV, but not if I destroyed it before passing it in. I realized the problem was that the callee didn't realize that the SV was mortal - I had made the hash mortal but not the *reference* to the hash. ANd of course the hash could never be destroyed until the reference to it was.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So, one of the big problems I&#8217;m having with kt3 is memory leaks. This is probably no surprise to anyone who has done XS programming before. I found one particularly pernicious one by using Devel::Leak.. this is in the log handler. Originally I had this, which I&#8217;m fairly sure I got from the internet somewhere: [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36,4],"tags":[],"_links":{"self":[{"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/posts\/4696"}],"collection":[{"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/comments?post=4696"}],"version-history":[{"count":3,"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/posts\/4696\/revisions"}],"predecessor-version":[{"id":4699,"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/posts\/4696\/revisions\/4699"}],"wp:attachment":[{"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/media?parent=4696"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/categories?post=4696"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.sheer.us\/weblogs\/wp-json\/wp\/v2\/tags?post=4696"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}