Recently we got ownership of a legacy piece of code with no knowledge
transfer and we cannot figure out why a certain line of code with
apr_dbd_pselect results in segmentation fault in the c code which is
deployed on Apache 2.4 using mysql on Amazon Linux2. The same piece of c
code works perfectly fine on Apache 2.2 and Centos with mysql same version.
Code in question is as follows. And the line throwing the seg fault is the
second call to apr_dbd_pselect (second last line in the code). This piece
of code basically makes use of the apr_dbd routines to make a select call
to get a value from a table given the argument and then we believe the
second select statement somehow ends up closing the
connection/statement/transaction on Centos with Apache 2.2. On Amazon linux
2 with Apache 2.4 it ends up throwing seg fault. We wanted to know why the
second select statement results in seg fault on AL2 and if it can be
rewritten in some other way to achieve the same result (as in closing
successfully the connection/statement/transaction) and not result in seg
fault. In both cases if we comment the line then the next invocation of
this method in same request results in this error-
https://dev.mysql.com/doc/mysql-errors/5.6/en/client-error-reference.html#error_cr_commands_out_of_sync

static char *method1(
        apr_pool_t      *tmp_pool,
        ap_dbd_t        *dbd,
        const char      *table_name,
        const char      *arg1)
{
        char                    *value = "";
        apr_dbd_results_t       *res = NULL;
        apr_dbd_row_t           *row = NULL;
        int                     ret;
        apr_dbd_prepared_t *jstmt;

        fprintf( stderr,"%s.%d Lookup token : %s\n",__FILE__,
__LINE__, arg1 );fflush(stderr);

        if (dbd == NULL)
        {
                fprintf( stderr,"%s.%d Could not open DBD
conenction",__FILE__, __LINE__);fflush(stderr);
                return "";
        }

        if (table_name == NULL || strlen(table_name) < 1)
        {
                table_name = "table1";
        }

        //char *stmt = "select fn from students where token = '12345'";
/* jdh -- table_name is not used can be used for prepared statement hash name */
        jstmt = apr_hash_get(dbd->prepared,table_name,APR_HASH_KEY_STRING);
        if (NULL == jstmt) {
                fprintf(stderr,"%s.%d Could not find prepared
statement: %s\n",__FILE__, __LINE__,table_name); fflush(stderr);
                return "";
        }

        const char *arglist[2];
        arglist[0] = arg1;

        ret = 
apr_dbd_pselect(dbd->driver,tmp_pool,dbd->handle,&res,jstmt,0,1,arglist);
        if      (0 != ret){
                fprintf(stderr,"%s.%d apr_dbd_pselect failed:
%d\n",__FILE__, __LINE__,ret); fflush(stderr);
                return "";
        }

        int rows = apr_dbd_num_tuples(dbd->driver, res);
        int cols = apr_dbd_num_cols(dbd->driver, res);

        fprintf( stderr,"%s.%d Rows, Cols : %i %i\n",__FILE__,
__LINE__, rows, cols );fflush(stderr);

        if (rows < 1 || cols < 1)
        {
                fprintf( stderr,"%s.%d No results found for
%s\n",__FILE__, __LINE__, token_id); fflush(stderr);
                return "";
        }

        ret = apr_dbd_get_row(dbd->driver, tmp_pool, res, &row, -1);
        if (0 == ret)
        {
                value = apr_dbd_get_entry(dbd->driver, row, 0);
                fprintf( stderr,"%s.%d Data, : %s\n",__FILE__,
__LINE__, value ); fflush(stderr);
        }
        else
        {
                fprintf( stderr,"%s.%d get_row fail
ret=%d\n",__FILE__, __LINE__, ret); fflush(stderr);
        }

        apr_dbd_pselect(dbd->driver,tmp_pool,dbd->handle,NULL,NULL,-2,0,NULL);
        return value;
}

Reply via email to