Thread: debugging C functions

debugging C functions

From
"Islam Hegazy"
Date:
Hi there
 
I wrote a C function to call from PostgreSQL8.2.4 under Linux. The functions returns unexpected results. I did an extensive analysis to the function and it seems correct. I want to know if there is a way to debug C functions that are passed to PostgreSQL.
 
Thanks
Islam

Re: debugging C functions

From
Joe Conway
Date:
Islam Hegazy wrote:
> I wrote a C function to call from PostgreSQL8.2.4 under Linux. The
> functions returns unexpected results. I did an extensive analysis to the
> function and it seems correct. I want to know if there is a way to debug
> C functions that are passed to PostgreSQL.

Yes. Something along these lines (where plr.so is an example shared
object library with a function called throw_notice installed in a
database called contrib_regression):

1. Build and install your function. Ensure both postgres and your
    library are built with debug symbols (--enable-debug)

2. start a psql session in the database where your function has
    been created

    #psql contrib_regression

3. Load the shared object library in psql

    contrib_regression=# load '$libdir/plr';
    LOAD

4. Start another console and determine the PID for the backend
    session (this will wrap poorly -- I'll do my best to make it
    readable)

    ps -ef | grep postgres

    postgres 24496     1  0 18:23 ?        00:00:00
      /usr/local/pgsql-dev/bin/postgres -D /opt/data/pgsql/data -p
      65432 -i -F
    postgres 24498 24496  0 18:23 ?        00:00:00
      postgres: writer process
    postgres 24499 24496  0 18:23 ?        00:00:00
      postgres: stats collector process
    postgres 24500 24496  0 18:23 ?        00:00:00
      postgres: autovacuum launcher process
    postgres 31233 24496  1 20:37 ?        00:00:00
      postgres: postgres contrib_regression [local] idle

   You want the PID associated with the idle session -- 31233

5. Run gdb and attach to the backend in question

    gdb /usr/local/pgsql-dev/bin/postgres 31233

6. Set breakpoints, etc, and then continue the gdb session

    [...]
    Reading symbols from
      /usr/lib64/R/library/stats/libs/stats.so...done.
    Loaded symbols for /usr/lib64/R/library/stats/libs/stats.so
    0x0000003fef4cdf45 in recv () from /lib64/libc.so.6
    (gdb) break throw_notice
    Breakpoint 1 at 0x636cb7: file plr.c, line 2908.
    (gdb) continue
    Continuing.

7. Return to the psql session, run your function

    contrib_regression=# select throw_notice('hello');

8. Return to gdb session, debug away...


HTH,

Joe

Re: debugging C functions

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> [ much good advice snipped, but I have to weigh in on one point ]

> 4. Start another console and determine the PID for the backend
>     session (this will wrap poorly -- I'll do my best to make it
>     readable)

"select pg_backend_pid()" is another alternative for finding the PID.

Personally I've gotten to the point where manually determining the
backend PID at all is tedious, and so I tend to use this script:

#!/bin/sh

# tee /dev/tty is for user to see the set of procs considered
PROCS=`ps auxww | \
    grep postgres: | \
    grep -v -e 'grep postgres:' -e 'postgres: stats' -e 'postgres: writer' -e 'postgres: archiver' -e 'postgres:
logger'| \ 
    tee /dev/tty | \
    awk '{print $2}'`

if [ `echo "$PROCS" | wc -w` -eq 1 ]
then
    exec gdb $PGINSTROOT/bin/postgres -silent "$PROCS"
else
    exec gdb $PGINSTROOT/bin/postgres -silent
fi

This fails (but gives you a list of processes to consider attaching to)
if there's more than one candidate.

            regards, tom lane

Re: debugging C functions

From
"Islam Hegazy"
Date:
Thanks for your replies, they were very helpful to me. Unfortuantely, I
can't trace the C function. PostgreSQL returns the results directly and the
debugger doesn't stop at the breakpoints in the C function.

I think the problem is in the pointers. I use pointers in my function and I
defined them as static to be preserved between calls, my function returns a
set of records. When I comment the pointers portion, the function works
well. But with the pointers, it hangs.

Any idea on how to deal with pointers issue?

Regards
Islam Hegazy

----- Original Message -----
From: "Tom Lane" <tgl@sss.pgh.pa.us>
To: "Joe Conway" <mail@joeconway.com>
Cc: "Islam Hegazy" <islheg@gawab.com>; <pgsql-general@postgresql.org>
Sent: Friday, June 01, 2007 11:38 PM
Subject: Re: [GENERAL] debugging C functions


> Joe Conway <mail@joeconway.com> writes:
>> [ much good advice snipped, but I have to weigh in on one point ]
>
>> 4. Start another console and determine the PID for the backend
>>     session (this will wrap poorly -- I'll do my best to make it
>>     readable)
>
> "select pg_backend_pid()" is another alternative for finding the PID.
>
> Personally I've gotten to the point where manually determining the
> backend PID at all is tedious, and so I tend to use this script:
>
> #!/bin/sh
>
> # tee /dev/tty is for user to see the set of procs considered
> PROCS=`ps auxww | \
>    grep postgres: | \
>    grep -v -e 'grep postgres:' -e 'postgres: stats' -e 'postgres:
> writer' -e 'postgres: archiver' -e 'postgres: logger' | \
>    tee /dev/tty | \
>    awk '{print $2}'`
>
> if [ `echo "$PROCS" | wc -w` -eq 1 ]
> then
>    exec gdb $PGINSTROOT/bin/postgres -silent "$PROCS"
> else
>    exec gdb $PGINSTROOT/bin/postgres -silent
> fi
>
> This fails (but gives you a list of processes to consider attaching to)
> if there's more than one candidate.
>
> regards, tom lane


Re: debugging C functions

From
Tom Lane
Date:
"Islam Hegazy" <islheg@gawab.com> writes:
> Thanks for your replies, they were very helpful to me. Unfortuantely, I
> can't trace the C function. PostgreSQL returns the results directly and the
> debugger doesn't stop at the breakpoints in the C function.

Well, you need to deal with that last, because you will never get very
far if you can't debug your code.

My experience is that gdb needs help to recognize a shared library's
symbols.  It works for me to LOAD the shared library (from SQL) before
attaching to the backend with gdb.  If you can't do that, gdb's
"sharedlibrary" command might do it.

            regards, tom lane

Re: debugging C functions

From
"Islam Hegazy"
Date:
I do the same but I use the ddd debugger
1) Load the shared library from the SQL
2) Open the .c file of my function
3) Place the break points
4) Execute the sql statement 'Select * from Myfn(...);'

The result is displayed and the debugger doesn't stop at the breakpoints.

Are there any steps missing?


Regards
Islam Hegazy


----- Original Message -----
From: "Tom Lane" <tgl@sss.pgh.pa.us>
To: "Islam Hegazy" <islheg@gawab.com>
Cc: "Joe Conway" <mail@joeconway.com>; <pgsql-general@postgresql.org>
Sent: Sunday, June 03, 2007 10:00 PM
Subject: Re: [GENERAL] debugging C functions


> "Islam Hegazy" <islheg@gawab.com> writes:
>> Thanks for your replies, they were very helpful to me. Unfortuantely, I
>> can't trace the C function. PostgreSQL returns the results directly and
>> the
>> debugger doesn't stop at the breakpoints in the C function.
>
> Well, you need to deal with that last, because you will never get very
> far if you can't debug your code.
>
> My experience is that gdb needs help to recognize a shared library's
> symbols.  It works for me to LOAD the shared library (from SQL) before
> attaching to the backend with gdb.  If you can't do that, gdb's
> "sharedlibrary" command might do it.
>
> regards, tom lane


Re: debugging C functions

From
Gregory Stark
Date:
"Islam Hegazy" <islheg@gawab.com> writes:

> I do the same but I use the ddd debugger
> 1) Load the shared library from the SQL
> 2) Open the .c file of my function
> 3) Place the break points
> 4) Execute the sql statement 'Select * from Myfn(...);'
>
> The result is displayed and the debugger doesn't stop at the breakpoints.

Are you sure you're attaching to the right process?

One way to do it is to run select pg_backend_pid() from psql and attach to
that pid.

--
  Gregory Stark
  EnterpriseDB          http://www.enterprisedb.com


Re: debugging C functions

From
"Islam Hegazy"
Date:
Yes, I am sure. If I placed a breakpoint in any file, e.g. execMain.c, the
debugger would enter this file.

Islam Hegazy


----- Original Message -----
From: "Gregory Stark" <stark@enterprisedb.com>
To: "Islam Hegazy" <islheg@gawab.com>
Cc: "Tom Lane" <tgl@sss.pgh.pa.us>; "Joe Conway" <mail@joeconway.com>;
<pgsql-general@postgresql.org>
Sent: Monday, June 04, 2007 5:50 AM
Subject: Re: [GENERAL] debugging C functions


> "Islam Hegazy" <islheg@gawab.com> writes:
>
>> I do the same but I use the ddd debugger
>> 1) Load the shared library from the SQL
>> 2) Open the .c file of my function
>> 3) Place the break points
>> 4) Execute the sql statement 'Select * from Myfn(...);'
>>
>> The result is displayed and the debugger doesn't stop at the breakpoints.
>
> Are you sure you're attaching to the right process?
>
> One way to do it is to run select pg_backend_pid() from psql and attach to
> that pid.
>
> --
>  Gregory Stark
>  EnterpriseDB          http://www.enterprisedb.com
>


Re: debugging C functions

From
"Islam Hegazy"
Date:
It worked today with me and I discovered what is the problem. The problem is
that I have 2 structures that contain pointers. I inistiate variables from
these structures as static. I can't declare the pointers inside the struct
as static. Now the problem is that when the function is called a second
time, it returns set of records, it finds the static pointers in the
function but the pointers inside the struct are deleted. Here is a portion
of the code:

typedef struct

{

int value;

struct TuplesList *next;

}TuplesList;

typedef struct

{

TuplesList *tuplesHead;

TuplesList *tuplesTail;

struct AggrQuery *nextQuery;

}AggrQuery;



Datum AggrFn(PG_FUNCTION_ARGS)

{

    static AggrQuery *queriesHead;

    static AggrQuery *queriesTail;

}

First call to AggrFn is correct, in the second call queriesHead and
queriesTail are preserved but queriesHead->tuplesHead, for example, is
rubbish from memory. I read in the PostgreSQL documentation 'However, if you
want to allocate any data structures to live across calls, you need to put
them somewhere else. The memory context referenced by multi_call_memory_ctx
is a suitable location for any data that needs to survive until the SRF is
finished running'. I don't understand this statement so I created the
variables as static but it is not working with struct....

Regards

Islam Hegazy



----- Original Message -----
From: "Gregory Stark" <stark@enterprisedb.com>
To: "Islam Hegazy" <islheg@gawab.com>
Cc: "Tom Lane" <tgl@sss.pgh.pa.us>; "Joe Conway" <mail@joeconway.com>;
<pgsql-general@postgresql.org>
Sent: Monday, June 04, 2007 5:50 AM
Subject: Re: [GENERAL] debugging C functions


> "Islam Hegazy" <islheg@gawab.com> writes:
>
>> I do the same but I use the ddd debugger
>> 1) Load the shared library from the SQL
>> 2) Open the .c file of my function
>> 3) Place the break points
>> 4) Execute the sql statement 'Select * from Myfn(...);'
>>
>> The result is displayed and the debugger doesn't stop at the breakpoints.
>
> Are you sure you're attaching to the right process?
>
> One way to do it is to run select pg_backend_pid() from psql and attach to
> that pid.
>
> --
>  Gregory Stark
>  EnterpriseDB          http://www.enterprisedb.com
>


pl/pgsql debuging, was Re: debugging C functions

From
David Gardner
Date:
This post got me thinking, is there a similar procedure for PL/pgSQL functions?

---
David Gardner, IT
The Yucaipa Companies
(310) 228-2855

-----Original Message-----
From: pgsql-general-owner@postgresql.org [mailto:pgsql-general-owner@postgresql.org] On Behalf Of Joe Conway
Sent: Friday, June 01, 2007 9:00 PM
To: Islam Hegazy
Cc: pgsql-general@postgresql.org
Subject: Re: [GENERAL] debugging C functions

Islam Hegazy wrote:
> I wrote a C function to call from PostgreSQL8.2.4 under Linux. The
> functions returns unexpected results. I did an extensive analysis to the
> function and it seems correct. I want to know if there is a way to debug
> C functions that are passed to PostgreSQL.

Yes. Something along these lines (where plr.so is an example shared
object library with a function called throw_notice installed in a
database called contrib_regression):

1. Build and install your function. Ensure both postgres and your
    library are built with debug symbols (--enable-debug)

2. start a psql session in the database where your function has
    been created

    #psql contrib_regression

3. Load the shared object library in psql

    contrib_regression=# load '$libdir/plr';
    LOAD

4. Start another console and determine the PID for the backend
    session (this will wrap poorly -- I'll do my best to make it
    readable)

    ps -ef | grep postgres

    postgres 24496     1  0 18:23 ?        00:00:00
      /usr/local/pgsql-dev/bin/postgres -D /opt/data/pgsql/data -p
      65432 -i -F
    postgres 24498 24496  0 18:23 ?        00:00:00
      postgres: writer process
    postgres 24499 24496  0 18:23 ?        00:00:00
      postgres: stats collector process
    postgres 24500 24496  0 18:23 ?        00:00:00
      postgres: autovacuum launcher process
    postgres 31233 24496  1 20:37 ?        00:00:00
      postgres: postgres contrib_regression [local] idle

   You want the PID associated with the idle session -- 31233

5. Run gdb and attach to the backend in question

    gdb /usr/local/pgsql-dev/bin/postgres 31233

6. Set breakpoints, etc, and then continue the gdb session

    [...]
    Reading symbols from
      /usr/lib64/R/library/stats/libs/stats.so...done.
    Loaded symbols for /usr/lib64/R/library/stats/libs/stats.so
    0x0000003fef4cdf45 in recv () from /lib64/libc.so.6
    (gdb) break throw_notice
    Breakpoint 1 at 0x636cb7: file plr.c, line 2908.
    (gdb) continue
    Continuing.

7. Return to the psql session, run your function

    contrib_regression=# select throw_notice('hello');

8. Return to gdb session, debug away...


HTH,

Joe

---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq


Re: pl/pgsql debuging, was Re: debugging C functions

From
"Pavel Stehule"
Date:
2007/6/5, David Gardner <David.Gardner@yucaipaco.com>:
> This post got me thinking, is there a similar procedure for PL/pgSQL functions?
>

No. You can debug PL/pgSQL function via debug plugin API. Currently
exists only one debugger, which can do it - Enterprisedb debugger.

Regards
Pavel Stehule