Opened 14 years ago

Closed 12 years ago

Last modified 12 years ago

#702 closed bug (fixed)

MingW ld.exe produces program which segfaults

Reported by: alistair@… Owned by:
Priority: lowest Milestone: 6.8.2
Component: Compiler Version: 6.4.1
Keywords: Cc: alistair@…
Operating System: Windows Architecture: x86
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

(from Alistair Bayley - alistair@…)

The C program below works correctly when compiled with GHC and ld 2.13.90, but segfaults on the first call to PQprepare when compiled with ld 2.15.91 (which ships with GHC 6.4.1) and also with ld 2.16.91. For now I have replaced the ld in C:\ghc\ghc-6.4.1\gcc-lib with ld-2.13.90 (from my MingW installation), but Sigbjorn Finn says that the more recent versions of ld are necessary for large GHCi libraries, so we can't just go back.

One possibly interesting datum (or maybe just a red herring) is this linker message emitted by 2.15.91 and 2.16.91, but not 2.13.90:

Info: resolving _PQprepare by linking to __imp__PQprepare (auto-import)

You'll need a full Postgres installation to reproduce this in its current state, unfortunately. The commands I use to run it are (assuming the default postgres database has been created, with user postgres, on localhost):

ghc -o test.exe test.c "-LC:\Program Files\PostgreSQL\8.1\bin" -lpq "-IC:\Program Files\PostgreSQL\8.1\include"
test.exe user=postgres

File: test.c

#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"

static void exit_nicely(PGconn *conn)
{
    PQfinish(conn);
    exit(1);
}

void check_error(PGconn *conn, PGresult *res, ExecStatusType rc, char *msg)
{
    if (PQresultStatus(res) != rc)
    {
        /* fprintf(stderr, msg, PQerrorMessage(conn)); */
        fprintf(stderr, "%s: %s\n", msg, PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
}

int main(int argc, char **argv)
{
    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    int         nFields;
    int         i,
                j;
        Oid paramTypes[10];

    /*
     * If the user supplies a parameter on the command line, use it as the
     * conninfo string; otherwise default to setting dbname=postgres and using
     * environment variables or defaults for all other connection parameters.
     */
    if (argc > 1)
        conninfo = argv[1];
    else
        conninfo = "dbname = postgres";

    /* Make a connection to the database */
    conn = PQconnectdb(conninfo);

    /* Check to see that the backend connection was successfully made */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn));
        exit_nicely(conn);
    }

    res = PQprepare(conn, "x", "DECLARE myportal CURSOR FOR select * from pg_database", 0, paramTypes);
    check_error(conn, res, PGRES_COMMAND_OK, "Prepare failed");
        
    /*
     * Our test case here involves using a cursor, for which we must be inside
     * a transaction block.  We could do the whole thing with a single
     * PQexec() of "select * from pg_database", but that's too trivial to make
     * a good example.
     */

    /* Start a transaction block */
    res = PQexec(conn, "BEGIN");
    check_error(conn, res, PGRES_COMMAND_OK, "BEGIN command failed");

    /*
     * Should PQclear PGresult whenever it is no longer needed to avoid memory
     * leaks
     */
    PQclear(res);

    /*
     * Fetch rows from pg_database, the system catalog of databases
     */
    res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
    check_error(conn, res, PGRES_COMMAND_OK, "DECLARE CURSOR failed");
    PQclear(res);

    res = PQexec(conn, "FETCH ALL in myportal");
    check_error(conn, res, PGRES_TUPLES_OK, "FETCH ALL failed");

    /* first, print out the attribute names */
    nFields = PQnfields(res);
    for (i = 0; i < nFields; i++)
        printf("%-15s", PQfname(res, i));
    printf("\n\n");

    /* next, print out the rows */
    for (i = 0; i < PQntuples(res); i++)
    {
        for (j = 0; j < nFields; j++)
            printf("%-15s", PQgetvalue(res, i, j));
        printf("\n");
    }

    PQclear(res);

    /* close the portal ... we don't bother to check for errors ... */
    res = PQexec(conn, "CLOSE myportal");
    PQclear(res);

    /* end the transaction */
    res = PQexec(conn, "END");
    PQclear(res);

    /* close the connection to the database and cleanup */
    PQfinish(conn);

    return 0;
}

Change History (4)

comment:1 Changed 13 years ago by igloo

Milestone: 6.8

I haven't confirmed this still happens with the latest GHC and ld.

comment:2 Changed 12 years ago by abayley

Cc: alistair@… added
Priority: normallowest

I suspect this was an issue with the Postgres libpq library, but was unable to confirm (problem posted to Postgres Interfaces list, but no responses). Lowest priority until I can confirm that it has gone away (or not).

comment:3 Changed 12 years ago by simonmar

Resolution: fixed
Status: newclosed

optimistically closing as fixed, if it crops up again please reopen.

comment:4 Changed 12 years ago by igloo

Milestone: 6.8 branch6.8.2
Note: See TracTickets for help on using tickets.