[freetds] freetds 0.61/tdslib SIGSEGV

Dan Podeanu pdan at extreme.ro
Thu May 8 16:34:05 EDT 2003


Sorry for the delay.. I took some time to track down the problem and the
answer to which I came is very strange. I'd be very curious to see if anyone
else can replicate this problem.

So, the bottom line would be that my test program crashes only when
linked with -pg (gcc gprof profiling). Compiling with -pg, but linking
without -pg appears to work ok (of course, it is more difficult to notice
something not crashing than something crashing, but I believe I'm right
here). The crash would happen within the first 30-60 seconds after
running it.

While compiled with -pg, the behavior alternates between displaying
'query failed' (tds_submit_query returned TDS_FAIL) and SIGSEGV-ing
(still in a FD_SET, although in various locations: goodread(), goodwrite(),
tds_check_socket_write()).

Note that I tested with two gcc versions, same behaviour:

gcc2.96:
Reading specs from /usr/lib/gcc-lib/i586-mandrake-linux-gnu/2.96/specs
gcc version 2.96 20000731 (Mandrake Linux 9.0 2.96-0.80mdk)

gcc3.2:
Reading specs from /usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.2/specs
Configured with:
../configure --prefix=/usr --libdir=/usr/lib --with-slibdir=/lib --mandir=/u
sr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posi
x --disable-checking --enable-long-long --enable-__cxa_atexit --enable-langu
ages=c,c++,ada,f77,objc,java --host=i586-mandrake-linux-gnu --with-system-zl
ib
Thread model: posix
gcc version 3.2 (Mandrake Linux 9.0 3.2-1mdk)


gdb SIGSEGV backtrace:

#0  0x400245df in goodread (tds=0x804b798, buf=0xbffff3c0 "", buflen=8) at
read.c:100
100                                     FD_SET(tds->s, &fds);
(gdb) backtrace
#0  0x400245df in goodread (tds=0x804b798, buf=0xbffff3c0 "", buflen=8) at
read.c:100
#1  0x40024a5e in tds_read_packet (tds=0x804b798) at read.c:374
#2  0x4002497d in tds_get_n (tds=0x804b798, dest=0xbffff430, need=3) at
read.c:289
#3  0x400248ae in tds_get_string (tds=0x804b798, dest=0x804b92c "", need=0)
at read.c:256
#4  0x40020a08 in tds7_get_data_info (tds=0x804b798, curcol=0x804b918) at
token.c:1077
#5  0x40020bb6 in tds7_process_result (tds=0x804b798) at token.c:1118
#6  0x4001fca9 in tds_process_result_tokens (tds=0x804b798,
result_type=0xbffff648) at token.c:426
#7  0x08049163 in mssql_query2 ()
#8  0x080493a0 in main ()
#9  0x400bf082 in __libc_start_main () from /lib/i686/libc.so.6

Again, please please please, someone check if this can be reproduced on
other
systems. An explanation would be welcome, as someone might debug better
than I do -- I'm not familiar with freetds's internals.

Much appreciated.
Dan.

PS. I noticed that running the test in a screen(1) window, and switching
between
screen windows seems to make it crash faster. Probably due to the fact that
screen
introduces some display delays and a race condition occurs (this somewhat
frightens
me, as it might be that the -pg only makes the race condition more
obvious -- as itself
introduces some delays due to recording of profile info -- but maybe I'm
just talking
out of my ass).

PS2. Test program (if you remove the -pg from the linking below, it will not
SIGSEGV)

------------------ cut here: begin of
compile.sh ----------------------------------
#!/bin/sh

g++ test.c -pg -c -o test.o
g++ test.o -pg -Wall -ltds -o test
------------------ cut here: end of
compile.sh ----------------------------------
------------------ cut here: begin of
test.c ----------------------------------
#include <stdlib.h>
#include <unistd.h>
#include <tds.h>
#include <tdsconvert.h>

TDSLOGIN *tds_login = NULL;
TDSSOCKET *tds_socket = NULL;

void mssql_restore_connection2() {
    TDSCONTEXT *tds_context;
    TDSCONNECTINFO *tds_connect_info;

    printf("attempting to (re)connect to the database server\n");

    if (tds_socket != NULL) {
        tds_free_socket(tds_socket);
        tds_socket = NULL;
    }

    if (tds_login != NULL) {
        tds_free_login(tds_login);
        tds_login = NULL;
    }

    if ((tds_login = tds_alloc_login()) == NULL) {
        fprintf(stderr, "failed to allocate login structure\n");
        exit(EXIT_FAILURE);
    }

    tds_set_passwd(tds_login, "akashadow");
    tds_set_user(tds_login, "linuxoperator");
    tds_set_app(tds_login, "cvsolsrv");
    tds_set_host(tds_login, "linux");
    tds_set_library(tds_login, "TDS-Library");
    tds_set_server(tds_login, "cc");
    tds_set_charset(tds_login, "iso_1");
    tds_set_language(tds_login, "us_english");
    tds_set_packet(tds_login, 512);
    tds_set_timeouts(tds_login, 5, 10, 120); /* connect, query, longquery */

    if ((tds_context = tds_alloc_context()) == NULL) {
        fprintf(stderr, "failed to alocate context\n");
        exit(EXIT_FAILURE);
    }
    if ((tds_socket = tds_alloc_socket(tds_context, 512)) == NULL) {
        fprintf(stderr, "failed to allocate socket\n");
        exit(EXIT_FAILURE);
    }

    tds_set_parent(tds_socket, NULL);

    tds_connect_info = tds_read_config_info(NULL, tds_login,
tds_context->locale);
    if (tds_connect_info == NULL) {
        tds_socket = NULL;
        tds_free_connect(tds_connect_info);
        tds_free_context(tds_context);

        fprintf(stderr, "failed to retrieve connection info\n");
        exit(EXIT_FAILURE);
    }
    if (tds_connect(tds_socket, tds_connect_info) == TDS_FAIL) {
        fprintf(stderr, "connection failed");
        tds_socket = NULL;
        tds_free_connect(tds_connect_info);
        tds_free_context(tds_context);

        fprintf(stderr, "failed to conenct to MSSQL\n");
        exit(EXIT_FAILURE);
    }

    printf("connected to the database server\n");
    printf("database server: server name: %s (%s), port: %d, TDS version:
%d.%d, block size: %d\n",
        tds_connect_info->server_name,
        tds_connect_info->ip_addr,
        tds_connect_info->port,
        tds_connect_info->major_version,
        tds_connect_info->minor_version,
        tds_connect_info->block_size);
    printf("database server: language: %s, charset: %s, timeouts: connect:
%d, query: %d, longquery: %d\n",
        tds_connect_info->language,
        tds_connect_info->char_set,
        tds_connect_info->connect_timeout,
        tds_connect_info->query_timeout,
        tds_connect_info->longquery_timeout);
    printf("database client: %s, app: %s, username: %s, pass: %s, library:
%s\n",
       tds_connect_info->host_name,
       tds_connect_info->app_name,
       tds_connect_info->user_name,
       tds_connect_info->password,
       tds_connect_info->library);

    tds_free_connect(tds_connect_info);
}

int mssql_query2(const char *query) {
    int rc, result_type;
    int row_type, compute_id;
    int i;
    unsigned char *src;
    TDS_INT srctype, srclen;
    CONV_RESULT res;

    TDSRESULTINFO *res_info;
    TDSCOLINFO *cur_col;

    printf("query: %s\n", query);

    if ((rc = tds_submit_query(tds_socket, query)) != TDS_SUCCEED) {
        fprintf(stderr, "query failed\n");
        exit(EXIT_FAILURE);
    }

    while ((rc = tds_process_result_tokens(tds_socket, &result_type)) ==
TDS_SUCCEED) {
        if ((res_info = tds_socket->res_info) == NULL) {
            return 0;
        }

        if (result_type == TDS_ROWFMT_RESULT) { /* result format */
            for (i = 0; i < res_info->num_cols; i++) {
                printf("row %d: %s\n", i,
res_info->columns[i]->column_name);
            }
        } else if (result_type == TDS_ROW_RESULT) { /* an actual row */
            while ((rc = tds_process_row_tokens(tds_socket, &row_type,
&compute_id)) == TDS_SUCCEED) {
                if (row_type != TDS_REG_ROW)
                    continue;

                for (i = 0; i < res_info->num_cols; i++) {
                    cur_col = res_info->columns[i];
                    src = &(res_info->current_row[cur_col->column_offset]);

                    if (is_blob_type(cur_col->column_type)) {
                        src = (unsigned char *)((TDSBLOBINFO
*)src)->textvalue;
                        srclen = cur_col->column_size;
                        srctype = cur_col->column_type;
                    } else {
                        src =
&(res_info->current_row[cur_col->column_offset]);
                        srclen = cur_col->column_size;
                        srctype = cur_col->column_type;
                    }

                    if (tds_convert(tds_socket->tds_ctx, srctype, (TDS_CHAR
*)src,
                                    srclen, SYBVARCHAR, &res) == TDS_FAIL)
                        continue;
                    printf("value %d: %s\n", i, res.c);
                }
            }
        } else if (result_type == TDS_CMD_FAIL) {
            return 0;
        }
    }

    return 1;
}

void mssql_close_connection() {
    tds_free_socket(tds_socket);
    tds_free_login(tds_login);
    printf("closing database connection\n");
}

int main(void) {
    mssql_restore_connection2();

    while (1) {
        printf("query result: %d\n", mssql_query2("SELECT 1 AS ONE"));
    }
    mssql_close_connection();
    return 0;
}

------------------ cut here: end of
test.c ----------------------------------

----- Original Message ----- 
From: "Frediano Ziglio" <freddyz77 at tin.it>
To: "FreeTDS Development Group" <freetds at lists.ibiblio.org>
Sent: Thursday, May 08, 2003 9:04 AM
Subject: Re: [freetds] freetds 0.61/tdslib SIGSEGV


> Il mer, 2003-05-07 alle 22:20, Dan Podeanu ha scritto:
> > I believe that there are some issues with freetds 0.61 - tdslib.
> > During a stability test, it crashes (SIGSEGV) constantly.
> >
> > What is curious is that this happens on a connection that has
> > timeouts set (tds_set_timeouts(tds_login, 5, 5, 5);), without
> > it everything appears to be fine.
> >
> > The stability tests consists in an endless loops of SELECT 1's,
> > sent to a MSSQL server (tds ver 7.0). Below is a gdb backtrace
> > of the crash:
> >
> > #0  0x400ae0af in tds_check_socket_write (tds=0x8121d28) at write.c:227
> > 227                     FD_SET(tds->s, &fds);
> > (gdb) backtrace
> > #0  0x400ae0af in tds_check_socket_write (tds=0x8121d28) at write.c:227
> > #1  0x400ae16c in goodwrite (tds=0x8121d28) at write.c:258
> > #2  0x400ae296 in tds_write_packet (tds=0x8121d28, final=0 '\0') at
> > write.c:304
> > #3  0x400adf4b in tds_put_byte (tds=0x8121d28, c=67 'C') at write.c:174
> > #4  0x400adce5 in tds_put_n (tds=0x8121d28, buf=0xbffdf6a0, n=30) at
> > write.c:84
> > #5  0x400adda2 in tds_put_string (tds=0x8121d28, s=0x1e <Address 0x1e
out of
> > bounds>, len=15) at write.c:114
> > #6  0x400b45f6 in tds_submit_query (tds=0x8121d28, query=0xbffdf870
"SELECT
> > 1 AS Foo") at query.c:99
> > #7  0x08053ed1 in mssql_query(__mssql__*, __client_type__*, char const*,
> > ...) (ms=0xbffef8a0, client=0x0,
> >     fmt=0x805d301 "SELECT 1 AS Foo") at mssql.c:195
> > #8  0x0804f1d1 in main (argc=0, argv=0xbffff96c) at cvsolsrv.c:564
> > #9  0x401c9082 in __libc_start_main () from /lib/i686/libc.so.6
> >
> > I can provide further information, if required. I can also replicate the
> > it quite easily.
> >
>
> Hi!
>
> I can't understand. Perhaps tds->s became -1 ??
>
> Can you post your test so I can add it to unittests ?
>
> Did you interrupt the communication with server ?
>
> bye
>   freddy77
>
>
> _______________________________________________
> FreeTDS mailing list
> FreeTDS at lists.ibiblio.org
> http://lists.ibiblio.org/mailman/listinfo/freetds
>




More information about the FreeTDS mailing list