Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-32495

Server crash on PS CALL execution, if SP has been changed after 1st execution

    XMLWordPrintable

Details

    Description

      If SP CALLhas been prepared and executed, and then the SP is changed(DROPped and CREATEd) by someone, the second execution of that CALL statement will reliably crash the server. The C API code to repeat

      MYSQL      *ma;
        MYSQL_STMT *stmt;
        MYSQL_BIND bind[3], paramBind[3];
        MARIADB_CHARSET_INFO *cs;
        my_bool    is_null= 0, error= 0;
        unsigned int i= 0, j= 0, res[3]={30,20,50}, param[3]= {30,20,50};
       
        ma = mysql_init(NULL);
        mysql_optionsv(ma, MYSQL_SET_CHARSET_NAME, "latin1");
       
        if (!mysql_real_connect(ma, "localhost", "root", "root", "test", 3306, NULL, CLIENT_MULTI_RESULTS | CLIENT_MULTI_STATEMENTS))
        {
          printf("Could not connect: %s\n", mysql_error(ma));
          exit(1);
        }
        else
        {
          printf("Server info %s\nClient info: %s\n",
          mysql_get_server_info(ma), mysql_get_client_info());
        }
       
        stmt= mysql_stmt_init(ma);
       
        mysql_query(ma, "DROP PROCEDURE IF EXISTS t_outparams");
        mysql_query(ma, "CREATE PROCEDURE t_outparams("
                    "  IN p_in INT, "
                    "  OUT p_out INT, "
                    "  INOUT p_inout INT) "
                    "BEGIN "
                    "  SET p_in = p_in*10, p_out = (p_in+p_inout)*10, p_inout = p_inout*10; "
                    "END");
        mysql_stmt_prepare(stmt, "CALL t_outparams(?,?,?)", -1);
       
        memset(&bind, 0, sizeof(bind));
        memset(&bind, 0, sizeof(paramBind));
       
        bind[0].buffer_type=  MYSQL_TYPE_LONG;
        bind[0].buffer=       (void *)res;
        bind[0].buffer_length= sizeof(int);
        bind[0].is_null=      NULL;
        bind[0].error=        NULL;
       
        bind[1].buffer_type=  MYSQL_TYPE_LONG;
        bind[1].buffer=       (void *)(res + 1);
        bind[1].buffer_length= sizeof(int);
        bind[1].is_null=      NULL;
        bind[1].error=        NULL;
       
        bind[2].buffer_type=  MYSQL_TYPE_LONG;
        bind[2].buffer=       (void *)(res + 2);
        bind[2].buffer_length= sizeof(int);
        bind[2].is_null=      NULL;
        bind[2].error=        NULL;
       
        mysql_stmt_bind_param(stmt, bind);
        mysql_stmt_execute(stmt);
        mysql_stmt_store_result(stmt);
        mysql_stmt_bind_result(stmt, bind);
       
        while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
        {
          printf("-- Values= %d %d %d\n", res[0], res[1], res[2]);
        }
        printf("---------------------------------------------------\n");
        mysql_stmt_next_result(stmt);
        if (mysql_stmt_field_count(stmt) == 0)
        {
          printf("SP returned: %lld", mysql_stmt_affected_rows(stmt));
        }
       
        mysql_query(ma, "DROP PROCEDURE t_outparams");
       
        mysql_query(ma, "CREATE PROCEDURE t_outparams("
          "  OUT p_out VARCHAR(19), "
          "  IN p_in INT, "
          "  INOUT p_inout INT) "
          "BEGIN "
          "  SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
          "  SELECT p_inout, p_in, substring(p_out, 9);"
          "END");
       
        mysql_stmt_bind_param(stmt, bind);
        mysql_stmt_execute(stmt);
        mysql_stmt_store_result(stmt);
        mysql_stmt_bind_result(stmt, bind);
       
        while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
        {
          printf("-- Values= %d %d %d\n", res[0], res[1], res[2]);
        }
        printf("---------------------------------------------------\n");
        mysql_stmt_next_result(stmt);
        mysql_stmt_close(stmt);
        
        mysql_query(ma, "DROP PROCEDURE t_outparams");
        mysql_close(ma);
      

      I don't have latest versions for all branches, but this crashes all supported server release series

      Server info 10.11.5-MariaDB
      Client info: 3.3.8
      -- Values= 3500 500 50
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Server info 10.5.20-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Server info 10.6.11-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Server info 10.4.31-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Server info 10.10.2-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Server info 10.9.4-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Could not connect: Can't connect to server on 'localhost' (10061)
      Server info 11.0.2-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      Server info 11.1.2-MariaDB
      Client info: 3.3.8
      -- Values= 20000 0 0
      ---------------------------------------------------
      SP returned: 0
      -- Values= 200 300 0
      ---------------------------------------------------
      Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
      ===================================================
      

      Unlikely this matters, but I am testing on Windows. The backtrace from the log:

      Server version: 10.11.5-MariaDB source revision: 7875294b6b74b53dd3aaa723e6cc103d2bb47b2c
      key_buffer_size=134217728
      read_buffer_size=131072
      max_used_connections=1
      max_threads=65537
      thread_count=1
      It is possible that mysqld could use up to 
      key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 142742958 K  bytes of memory
      Hope that's ok; if not, decrease some variables in the equation.
       
      Thread pointer: 0x1a98daccf98
      Attempting backtrace. You can use the following information to find out
      where mysqld died. If you see no messages after this, something went
      terribly wrong...
      server.dll!my_convert()[ctype.c:1267]
      server.dll!String::copy()[sql_string.cc:476]
      server.dll!Protocol::net_store_data_cs()[protocol.cc:104]
      server.dll!Protocol_text::store_field_metadata()[protocol.cc:854]
      server.dll!Protocol::send_result_set_metadata()[protocol.cc:1213]
      server.dll!Protocol_binary::send_out_parameters()[protocol.cc:1965]
      server.dll!Prepared_statement::execute()[sql_prepare.cc:5335]
      server.dll!Prepared_statement::execute_loop()[sql_prepare.cc:4646]
      server.dll!mysql_stmt_execute_common()[sql_prepare.cc:3578]
      server.dll!mysqld_stmt_execute()[sql_prepare.cc:3352]
      server.dll!dispatch_command()[sql_parse.cc:1826]
      server.dll!do_command()[sql_parse.cc:1407]
      server.dll!tp_callback()[threadpool_common.cc:245]
      KERNEL32.DLL!TermsrvSetKeySecurity()
      ntdll.dll!RtlEqualUnicodeString()
      ntdll.dll!TpReleaseCleanupGroupMembers()
      KERNEL32.DLL!BaseThreadInitThunk()
      ntdll.dll!RtlUserThreadStart()
       
      Trying to get some variables.
      Some pointers may be invalid and cause the dump to abort.
      Query (0x1a98db75090): CALL t_outparams(?,?,?)
      Connection ID (thread ID): 12
      Status: NOT_KILLED
       
      Optimizer switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off
      

      I did not dig much, but looks like the order of in/out parameters is what matters here - in original test the first change of procedure did not change that, but added a resultset, and it did not crash the server.

      Not sure if it's critical - unlikely something that people do on production systems, but it's still a crash.

      Attachments

        Activity

          People

            shulga Dmitry Shulga
            Lawrin Lawrin Novitsky
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.