PEPPLER.ORG
Michael Peppler
Sybase Consulting
Menu
Home
Sybase on Linux
Install Guide for Sybase on Linux
General Sybase Resources
General Perl Resources
Freeware
Sybperl
Sybase::Simple
DBD::Sybase
BCP Tool
Bug Tracker
Mailing List Archive
Downloads Directory
FAQs
Sybase on Linux FAQ
Sybperl FAQ
Personal
Michael Peppler's resume

sybperl-l Archive

Up    Prev    Next    

From: "Masatsuyo Takahashi" <freesemt at mx2 dot nisiq dot net>
Subject: Memory leak report
Date: Apr 25 1998 3:41AM

Hello,

I am rather new to the mailing list, although I've been using Sybperl
for more than three years. I really enjoy programming Sybperl.

Having read messages on memory leaks in Sybase::CTlib last week,
I thought it might be better to post this report.

I have a similar problem with it.

In my case, leaks seem to occur on the following conditions:

	(C1) repeated calls to ct_execute() with the same handle

	(C2) callbacks to servermsg_cb(), which occur in case of errors

Struggling with CTlib.xs, I've found that the following modifications
seem to PARTIALLY improve the problem, i.e., (C1) only,
while they do not completely solve it, i.e., not yet (C2).

	(M1) Add "cleanUp(info);"  to the entry of describe()

	(M2) "describe(info, NULL, 0);" AFTER, instead of BEFORE,
	     "newdbh()" in servermsg_cb()

	(M3) "cleanUp(info);" when New(902, info, 1, ConInfo) has been done

The question is whether I am digging around in the RIGHT direction,
rather than making it worse or degrade.

I am using sybperl-2.09 with Sybase 11 on AIX 4.2.

Test scripts for (C1) and (C2) are attched as separate files.
(The test script for C2 creates, inserts rows into, and drops a table.
 Be sure to check if you run it.)

Output of (C2), after (M1)..(M3) are applied, is as follows:

[1]	takahasi 17734 50.0  3.0 1624 1800  pts/5 A    18:01:21  0:01 perl5 leak_test2.
[100]	takahasi 17734 16.7  3.0 1664 1840  pts/5 A    18:01:21  0:01 perl5 leak_test2.
[200]	takahasi 17734 22.2  3.0 1704 1880  pts/5 A    18:01:21  0:02 perl5 leak_test2.
[300]	takahasi 17734 23.1  3.0 1740 1916  pts/5 A    18:01:21  0:03 perl5 leak_test2.
[400]	takahasi 17734 25.0  3.0 1776 1952  pts/5 A    18:01:21  0:04 perl5 leak_test2.
[500]	takahasi 17734 20.0  3.0 1816 1992  pts/5 A    18:01:21  0:04 perl5 leak_test2.
[600]	takahasi 17734 21.7  3.0 1852 2028  pts/5 A    18:01:21  0:05 perl5 leak_test2.
[700]	takahasi 17734 25.9  3.0 1892 2068  pts/5 A    18:01:21  0:07 perl5 leak_test2.
[800]	takahasi 17734 23.3  3.0 1928 2104  pts/5 A    18:01:21  0:07 perl5 leak_test2.
[900]	takahasi 17734 23.5  3.0 1964 2140  pts/5 A    18:01:21  0:08 perl5 leak_test2.
[1000]	takahasi 17734 24.3  3.0 2004 2180  pts/5 A    18:01:21  0:09 perl5 leak_test2.
				 ****
				 ****
You can see the memory required by the process increased from 1624
to 2004 KB. The number in brackets at the top of each line indicates
the total number of iteration up to that point.

The result shows that about 400byte leak per callback still remains for (C2).

Note that, in this script, I have suppressed error messages 2601 and 3621
which  otherwise would have told you about duplicate key value errors.

Lists for (M1),(M2), and (M3) are shown below.

I hope this report will give a hint to the problem.

Masatsuyo
-----------------------
Masatsuyo Takahashi
freesemt@mx2.nisiq.net

-----------------------------------------------------------------------

(M1) Add "cleanUp(info);"  to the entry of describe()

line#
1025	static CS_RETCODE
1026	describe(info, dbp, restype)
1027	    ConInfo *info;
1028	    SV *dbp;
1029	    int restype;
1030	{
1031	    CS_RETCODE retcode;
1032	    int i;
1033	    int use_datetime = 0;
1034	    int use_money = 0;
1035	    int use_numeric = 0;
1036	    
	    cleanUp(info);	/* <--- add (M1) */

1037	    if((retcode = ct_res_info(info->cmd, CS_NUMDATA,
1038				      &info->numCols, CS_UNUSED, NULL)) != CS_SUCCEED)
1039	    {
1040		warn("ct_res_info() failed");
1041		goto GoodBye;
1042	    }


(M2) "describe(info, NULL, 0);" after, instead of before, "newdbh()" in
servermsg_cb()
(M3) "cleanUp(info);" when New(902, info, 1, ConInfo) has been done

line#
1435	static CS_RETCODE
1436	servermsg_cb(context, connection, srvmsg)
1437	CS_CONTEXT	*context;
1438	CS_CONNECTION	*connection;
1439	CS_SERVERMSG	*srvmsg;
1440	{
1441	    CS_COMMAND	*cmd;
1442	    CS_RETCODE	retcode;
1443	    dTHR;
1444	    
1445	    if(server_cb.sub)	/* a perl error handler has been installed */
1446	    {
1447		dSP;
1448		SV *sv, **svp;
1449		HV *hv;
1450		char *package = "Sybase::CTlib";
1451		int retval, count;
1452		ConInfo *info;
1453		RefCon *refCon;
		int	new_info;	/* <--- add (M3)-1 */
1454	
1455		ENTER;
1456		SAVETMPS;
1457		PUSHMARK(sp);
1458		    
		new_info = 0;		/* <--- add (M3)-2 */
1459		if (srvmsg->status & CS_HASEED)
1460		{
1461		    if (ct_con_props(connection, CS_GET, CS_EED_CMD,
1462				     &cmd, CS_UNUSED, NULL) != CS_SUCCEED)
1463		    {
1464			warn("servermsg_cb: ct_con_props(CS_EED_CMD) failed");
1465			return CS_FAIL;
1466		    }
1467	
1468		    New(902, info, 1, ConInfo);
		    new_info = 1;	/* <--- add (M3)-3 */
1469		    if((hv = perl_get_hv("Sybase::CTlib::_refCon", FALSE)))
1470		    {
1471			if((svp = hv_fetch(hv, (char*)connection, sizeof(connection), 0)))
1472			{
1473			    refCon = (RefCon*)SvIV(*svp);
1474			    info->connection = refCon;
1475			}
1476		    }
1477		    info->cmd = cmd;
1478		    info->numCols = 0;
1479		    info->coldata = NULL;
1480		    info->datafmt = NULL;
1481		    info->type = CON_EED_CMD;
1482		    ++info->connection->refcount;
1483	
1484		    /* describe(info, NULL, 0);	<--- del (M2)-1 */
1485	
1486		    sv = newdbh(info, package, &sv_undef, NULL);
1487		    if(!SvROK(sv))
1488			croak("The newly created dbh is not a reference (this should never happen!)");
		    describe(info, NULL, 0);	/* <--- add (M2)-2 */
1489		    info->attr.ExtendedError = TRUE;
1490		    if(debug_level & TRACE_CREATE)
1491			warn("Created %s", neatsvpv(sv, 0));
1492		    
1493		    XPUSHs(sv_2mortal(sv));
1494		}
1495		else
1496		    XPUSHs(&sv_undef);
1497		
1498		XPUSHs(sv_2mortal(newSViv(srvmsg->msgnumber)));
1499		XPUSHs(sv_2mortal(newSViv(srvmsg->severity)));
1500		XPUSHs(sv_2mortal(newSViv(srvmsg->state)));
1501		XPUSHs(sv_2mortal(newSViv(srvmsg->line)));
1502		if(srvmsg->svrnlen > 0)
1503		    XPUSHs(sv_2mortal(newSVpv(srvmsg->svrname, 0)));
1504		else
1505		    XPUSHs(&sv_undef);
1506		if(srvmsg->proclen > 0)
1507		    XPUSHs(sv_2mortal(newSVpv(srvmsg->proc, 0)));
1508		else
1509		    XPUSHs(&sv_undef);
1510		XPUSHs(sv_2mortal(newSVpv(srvmsg->text, 0)));
1511	
1512		
1513		PUTBACK;
1514		if((count = perl_call_sv(server_cb.sub, G_SCALAR)) != 1)
1515		    croak("An error handler can't return a LIST.");

		if (new_info) {		/* <--- add (M3)-4 */
		    cleanUp(info);	/* <--- add (M3)-5 */
		    /* Safefree(info);	this ends up in core dump! */
		}			/* <--- add (M3)-6 */

1516		SPAGAIN;
1517		retval = POPi;
1518		
1519		PUTBACK;
1520		FREETMPS;
1521		LEAVE;
1522		
1523		return retval;
1524	    }
1525	    else
1526	    {
1527		/* Don't print informational messages... */

__END__