function crashes backend - Mailing list pgsql-hackers

From Louis-David Mitterrand
Subject function crashes backend
Date
Msg-id 20000927085358.A9646@styx
Whole thread Raw
Responses Re: function crashes backend
List pgsql-hackers
Hello,

I am writing a SPI function to run maintenance tasks on my auction
system but it keeps crashing the backend after running only one loop.
Now, I am not a C programmer, nor do I have any formal training in CS. I
thought I might run this function by you guys so that a cursory look
might reveal some obvious coding mistake? 

Thanks in advance for your insight.

int4 auction_maintenance(void) {
char * query, * default_locale = getenv("LC_ALL");bool current, isnull;int i;
/* Connect to SPI manager */if (SPI_connect() != SPI_OK_CONNECT)    elog(ERROR, "bid_control.c: SPI_connect failed");

/*    asprintf(&query, "BEGIN");SPI_exec(query, 0);free(query);*/
/* check if last modification time of special user id 0 is less than 15 * minutes ago */asprintf(&query, "SELECT
((now()::abstime::int4- modified::abstime::int4) \        / 60) < 15 AS current FROM person WHERE id = 0 FOR
UPDATE");SPI_exec(query,0);free(query);
 
current = DatumGetChar(SPI_getbinval(        SPI_tuptable->vals[0], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"current"), &isnull));
 
if (current) {    /* maintenance script ran less that 15 minutes ago, do nothing     */
/*        asprintf(&query, "COMMIT");    SPI_exec(query, 0);    free(query);*/
    elog(NOTICE, "auction system still current");
    SPI_finish();    return current;}
/* update modification time now, locking other daemons out */asprintf(&query, "UPDATE person SET modified = now() WHERE
id= 0");SPI_exec(query, 0);free(query);
 

/*    asprintf(&query, "COMMIT");SPI_exec(query, 0);free(query);*/
/* start real mainenance work here */

/*    asprintf(&query, "BEGIN");SPI_exec(query, 0);free(query);*/
/* select all auctions that have expired and have not been notified */asprintf(&query, "SELECT *,auction_status(a.id),
\   seller.mail AS seller_mail, seller.locale  AS seller_locale, \    seller.login AS seller_login \    FROM auction a,
personseller WHERE auction_status(a.id) <= 0 \    AND a.person_id = seller.id \    AND (notified IS FALSE OR notified
ISNULL) FOR UPDATE");SPI_exec(query, 0);free(query);
 
for (i = SPI_processed - 1; i >= 0; i--) {
    int type = DatumGetInt32(SPI_getbinval(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"type"), &isnull));
 
    char * title = SPI_getvalue(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"title"));
 
    char * seller_mail = SPI_getvalue(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"seller_mail"));
 
    char * seller_locale = SPI_getvalue(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"seller_locale"));
 
    char * seller_login = SPI_getvalue(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"seller_login"));
 
    char * stopdate = SPI_getvalue(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"stopdate"));
 
    int auction_id = DatumGetInt32(SPI_getbinval(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"id"), &isnull));
 
    int lot = DatumGetInt32(SPI_getbinval(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"lot"), &isnull));
 
    int auction_status = DatumGetInt32(SPI_getbinval(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
 SPI_fnumber(SPI_tuptable->tupdesc, "auction_status"), &isnull));
 
    int renew_count = DatumGetInt32(SPI_getbinval(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"renew_count"), &isnull));
 

/*        bool auto_renew = DatumGetChar(SPI_getbinval(            SPI_tuptable->vals[i], SPI_tuptable->tupdesc,
   SPI_fnumber(SPI_tuptable->tupdesc, "auto_renew"), &isnull));*/
 
    elog(NOTICE, "Processing auction #%d of %d (\n"            "type: %d\n"            "title: %s\n"
"seller_mail:%s\n"            "seller_locale: %s\n"            "seller_login: %s\n"            "stopdate: %s\n"
  "id: %d\n"            "lot: %d\n"            "status: %d\n"            "renew_count: %d\n"            ")",
SPI_processed- i, SPI_processed,             type,            title,             seller_mail,            seller_locale,
          seller_login,            stopdate,            auction_id,             lot,            auction_status,
  renew_count            );
 
    /* FIRST, store a copy of this auction in the archive, before eventually     * running UPDATE or DELETE on it
*/   asprintf(&query, "INSERT INTO auction_archive SELECT * FROM auction \        WHERE id = %d", auction_id);
SPI_exec(query,0);    free(query);
 
    /* store a copy of all bids into archive     */    asprintf(&query, "INSERT INTO bid_archive SELECT * FROM bid \
   WHERE auction_id = %d", auction_id);    SPI_exec(query, 0);    free(query);
 
/*#if 0*/    /* winner/seller notification     */    if (auction_status != -lot) { /* something was sold */        char
*mess;        char **bidder_login, **bidder_mail, **bidder_locale;        int *bid_lot, *bidder_id, j, l;        double
*bid_price;
        /* get high bidders         */        asprintf(&query, "SELECT max(b.lot) AS bid_lot, \            max(b.price)
ASbid_price,p.login AS bidder_login, \            p.id AS bidder_id, p.mail AS bidder_mail, \            p.locale AS
bidder_locale\            FROM bid b, person p \            WHERE b.auction_id = %d AND p.id = b.person_id \
GROUPBY p.login, p.id, p.mail,p.locale \            ORDER BY max(price)", auction_id);        SPI_exec(query, 0);
free(query);
 
        bid_price = alloca(SPI_processed * sizeof(double));        bid_lot = alloca(SPI_processed * sizeof(int));
bidder_id = alloca(SPI_processed * sizeof(int));
 
        bidder_login = alloca(SPI_processed * sizeof(char*));        bidder_mail = alloca(SPI_processed *
sizeof(char*));       bidder_locale = alloca(SPI_processed * sizeof(char*));
 

/*            elog(NOTICE, "starting winner/seller notification on auction #%d",                auction_id);*/
        /* get winner list         */        for (j = SPI_processed - 1; j >= 0; j--) {            bid_price[j] =
*DatumGetFloat64(SPI_getbinval(                   SPI_tuptable->vals[j], SPI_tuptable->tupdesc,
SPI_fnumber(SPI_tuptable->tupdesc,"bid_price"),                    &isnull));
 
            bid_lot[j] = DatumGetInt32(SPI_getbinval(                    SPI_tuptable->vals[j], SPI_tuptable->tupdesc,
                 SPI_fnumber(SPI_tuptable->tupdesc, "bid_lot"),                    &isnull));
 
            bidder_id[j] = DatumGetInt32(SPI_getbinval(                    SPI_tuptable->vals[j],
SPI_tuptable->tupdesc,                   SPI_fnumber(SPI_tuptable->tupdesc, "bidder_id"),
&isnull));
            bidder_login[j] = SPI_getvalue(                    SPI_tuptable->vals[j], SPI_tuptable->tupdesc,
       SPI_fnumber(SPI_tuptable->tupdesc, "bidder_login"));
 
            bidder_mail[j] = SPI_getvalue(                    SPI_tuptable->vals[j], SPI_tuptable->tupdesc,
      SPI_fnumber(SPI_tuptable->tupdesc, "bidder_mail"));
 
            bidder_locale[j] = SPI_getvalue(                    SPI_tuptable->vals[j], SPI_tuptable->tupdesc,
        SPI_fnumber(SPI_tuptable->tupdesc, "bidder_locale"));
 
            elog(NOTICE, "extracting winner %s for price %f and lot %d",                    bidder_login[j],
bid_price[j],bid_lot[j]);            /* decrease available quantity marker until all is sold, dutch             *
auctionsonly             */
 
/*                l -= bid_lot[i];*/
        }
        if (type == AUCTION_CLASSIC) {            char * winner = NULL;            double final_price;
/*                winner = astrcat();*/            /* determine final_price for dutch auction: the lowest of the
    * winning bids             */            for (j = SPI_processed - 1, l = lot; j >= 0 && l > 0;
j--,l -= bid_lot[j]) {                final_price = bid_price[j];            }            for (j = SPI_processed - 1, l
=lot; j >= 0 && l > 0;                    j--, l -= bid_lot[j]) {
 
                /* start building the string listing winners (for dutch)                 * or the only winner (for
normal)                */                setlocale(LC_ALL, seller_locale);                setenv("LC_ALL",
seller_locale,1);
 
                asprintf(&mess, _(                        "* login: %s, \t"                        "e-mail: %s, \t"
                  "bid price: %.2f, \t"                        "bid quantity: %d, \t"                        "final
price:%.2f,\t"                        "alloted quantity: %d,\t"                        ),
bidder_login[j],bidder_mail[j], bid_price[j],                        bid_lot[j], final_price,
(bid_lot[j]< l ? l : bid_lot[j]) );                astrcat(&winner, mess);                free(mess);
 
                elog(NOTICE, "winner #%d is %s", j, winner);
                setlocale(LC_ALL, bidder_locale[j]);                setenv("LC_ALL", bidder_locale[j], 1);
 /* notify winner directly                 */                asprintf(&mess, _(
 
"\tDear %s,\n"
"\n"
"On the following closed auction:"
"\n"
"- title: %s\n"
"- id: %d\n"
"- end date: %s\n"
"- seller: %s\n"
"- seller e-mail: %s\n"
"\n"
"You have entered this winning bid:\n"
"\n"
"- bid price: %.2f\n"
"- bid quantity: %d\n"
"- final price: %.2f\n"
"- alloted quantity: %d\n"
"\n"
"Please contact the seller as soon as possible to close the transaction\n"
"\n"
"-- \n"
"Apartia auction daemon\n"                ), bidder_login[j], title,                auction_id, stopdate, seller_login,
seller_mail,               bid_price[j], bid_lot[j], final_price,                (bid_lot[j] < l ? l : bid_lot[j]));
           sendmail(bidder_mail[j], "Auction win notification", mess);                free(mess);
 
                /* decrease available quantity marker until all is sold,                 * dutch auctions only
      */                l -= bid_lot[j];            }
 
            /* now notify the seller with a list of winning bids             */            asprintf(&mess, _(
"\tDear %s,\n"
"\n"
"On your closed auction:\n"
"\n"
"- title: %s\n"
"- id: %d\n"
"- end date: %s\n"
"\n"
"The following winning bid(s) have been placed:\n"
"%s\n"
"\n"
"Please contact the winner(s) as soon as possible to close the transaction\n"
"-- \n"
"Apartia auction daemon\n"),            seller_login, title, auction_id, stopdate, winner            );
free(winner);           sendmail(seller_mail,                    _("Auction successful close notification"), mess);
      free(mess);
 

        } else if (type == AUCTION_REVERSE || type == AUCTION_FIXED) {        } else if (type == AUCTION_BID) {
}
        /* clean up memory         */
/*            free(bid_price);        free(bid_lot);        free(bidder_mail);        free(bidder_login);
free(bidder_locale);       free(bidder_id);*/    }
 
    /* DELETE all old bids     */    asprintf(&query, "DELETE FROM bid WHERE auction_id = %d",            auction_id);
 SPI_exec(query, 0);    free(query);
 
    asprintf(&query, "DELETE FROM autobid WHERE auction_id = %d",            auction_id);    SPI_exec(query, 0);
free(query);
    /* renew expired auctions with unsold lots     */    if (auction_status < 0 && renew_count > 0) {
asprintf(&query,"UPDATE auction SET startdate = now(), \            stopdate = now() + (stopdate - startdate), \
   renew_count = renew_count - 1, \            lot = -auction_status(id), notified = FALSE, \            WHERE id =
%d",auction_id);        SPI_exec(query, 0);        free(query);
 
        /* localize message, numbers, dates         */        setlocale(LC_ALL, seller_locale);        setenv("LC_ALL",
seller_locale,1);
 
        /* notify seller of renewal         */        asprintf(&query, _(
"\tDear %s\n"
"\n"
"Your expired auction:\n"
"- title: %s\n"
"- id: %d\n"
"- end date: %s\n"
"\n"
"has been auto-renewed today with the same duration.\n"
"\n"
"Greetings\n"
"-- \n"
"The auction daemon\n"        ), seller_login, title, auction_id, stopdate);        sendmail(seller_mail, _("Auction
renewalnotice"), query);        free(query);    } else {
 
        /* auction was closed and fully sold OR not auto_renewed,         */        asprintf(&query, "DELETE FROM
auctionWHERE id = %d", auction_id);        SPI_exec(query, 0);        free(query);
 
        /* only notify if nothing was sold; when something has been sold         * normal winner/seller notification
hasalready taken place         * higher in this code         */        if (auction_status == -lot) {
setlocale(LC_ALL,seller_locale);            setenv("LC_ALL", seller_locale, 1);            /* notify seller of auction
end            */            asprintf(&query, _(
 
"\tDear %s\n"
"\n"
"Your expired auction:\n"
"- title: %s\n"
"- id: %d\n"
"- end date: %s\n"
"\n"
"Has been removed from the system.\n"
"\n"
"-- \n"
"The auction daemon\n"            ), seller_login, title, auction_id, stopdate);            sendmail(seller_mail,
_("Auctionexpiration notice"), query);            free(query);        }    }
 
/*#endif*/    elog(NOTICE, "End of loop %d", i);}
/* restore default locale */setlocale(LC_ALL, default_locale);setenv("LC_ALL", default_locale, 1);

/*    asprintf(&query, "COMMIT");SPI_exec(query, 0);free(query);*/
SPI_finish();return current;
}

-- 
Louis-David Mitterrand - ldm@apartia.org - http://www.apartia.org

Radioactive cats have 18 half-lives.


pgsql-hackers by date:

Previous
From: "Mikheev, Vadim"
Date:
Subject: RE: RE: [GENERAL] update inside transaction violates un ique constraint?
Next
From: Hiroshi Inoue
Date:
Subject: Re: libpq static link library dowsn't work (M$ VS6)