Description:
MySQL crashes when executing the following stored procedure:
CREATE PROCEDURE OSNodeGet(id int8)
BEGIN
DECLARE objid INT8 DEFAULT 0;
DECLARE cp, c INT DEFAULT 0;
DECLARE done INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
DECLARE node_id, node_parent, node_next, node_prev, node_ctime,
node_mtime, object_id, obj_id, object_class,
class_id, class_cat, prop_mime_id,
prop_maxsize, prop_minsize INT8;
DECLARE class_name, class_desc, object_name, prop_name, prop_mime,
prop_encoding, prop_prompt TEXT;
DECLARE oprop_id, oprop_cp, oprop_int8, oprop_int4, oprop_int2,
oprop_int1, oprop_object INT8;
DECLARE oprop_type, oprop_char, oprop_text TEXT;
DECLARE curs CURSOR FOR SELECT op_id, op_type, op_cp,
op_value_int8,
op_value_int4,
op_value_int2,
op_value_int1,
op_value_char,
op_value_text,
op_value_object
FROM object_property
WHERE op_object = objid;
CREATE TEMPORARY TABLE nodeget
SELECT * FROM node WHERE no_id = id;
SELECT @objid:=no_object FROM nodeget;
SELECT @objid:=no_object FROM nodeget;
SELECT count(*) INTO c FROM nodeget;
SELECT c; -- here there's a crash
IF c > 0 AND @objid > 0 THEN
CREATE TEMPORARY TABLE obj_get
SELECT * FROM object,class WHERE obj_id=@objid AND
class.cl_id = obj_class;
SELECT * FROM obj_get;
SELECT no_id, no_parent, no_next, no_prev, no_ctime,
no_mtime, no_object, obj_id, obj_class, obj_name,
class.cl_id, class.cl_category, class.cl_name,
class.cl_desc
INTO
node_id, node_parent, node_next,
node_prev, node_ctime, node_mtime,
object_id, obj_id, object_class,
object_name, class_id, class_cat,
class_name, class_desc
FROM nodeget, obj_get, class
WHERE class.cl_id = obj_class;
SELECT no_id, no_parent, no_next, no_prev, no_ctime,
no_mtime, no_object, obj_id, obj_class, obj_name
FROM nodeget, obj_get;
CREATE TEMPORARY TABLE result (
node_id int4,
node_parent int4,
node_next int4,
node_prev int4,
node_ctime int4,
node_mtime int4,
object_id int4,
object_name text,
object_class text,
class_desc text,
property_type text,
property_name text,
property_prompt text,
property_value text,
property_mime text,
property_encoding text,
property_maxsize int4,
property_minsize int4
);
SELECT count(*) INTO cp FROM object_property WHERE op_object=@objid;
IF cp > 0 THEN
OPEN curs;
properties: REPEAT
FETCH curs INTO oprop_id, oprop_type, oprop_cp,
oprop_int8, oprop_int4, oprop_int2,
oprop_int1, oprop_char, oprop_text,
oprop_object;
CASE oprop_type
WHEN 'int8' THEN SET @prop_val=oprop_int8;
WHEN 'int4' THEN SET @prop_val=oprop_int4;
WHEN 'int2' THEN SET @prop_val=oprop_int2;
WHEN 'int1' THEN SET @prop_val=oprop_int1;
WHEN 'char' THEN SET @prop_val=oprop_char;
WHEN 'text' THEN SET @prop_val=oprop_int8;
WHEN 'obje' THEN SET @prop_val=oprop_object;
END CASE;
SELECT cp_name, cp_prompt, cp_maxsize, cp_minsize,
cp_mimetype INTO
prop_name, prop_prompt,
prop_maxsize, prop_minsize,
prop_mime_id FROM class_property
WHERE cp_id = oprop_cp;
SELECT mime_name, mime_encoding INTO prop_mime,
prop_encoding FROM mimetype
WHERE mime_id = prop_mime_id;
INSERT INTO result VALUES (
node_id,
node_parent,
node_next,
node_prev,
node_ctime,
node_mtime,
object_id,
object_name,
class_name,
class_desc,
oprop_type,
prop_name,
prop_prompt,
@prop_val,
prop_mime,
prop_encoding,
prop_maxsize,
prop_minsize
);
UNTIL done END REPEAT properties;
CLOSE curs;
ELSE
INSERT INTO result VALUES (
node_id,
node_parent,
node_next,
node_prev,
node_ctime,
node_mtime,
object_id,
object_name,
class_name,
class_desc,
oprop_type,
prop_name,
prop_prompt,
@prop_val,
prop_mime,
prop_encoding,
prop_maxsize,
prop_minsize);
END IF;
DROP TABLE nodeget;
DROP TABLE obj_get;
SELECT * FROM result;
DROP TABLE result;
END IF;
END|
mysqld ends with a SIGSEGV when I try to SELECT a local variable declared as INT 8 and set by SELECT count(*) INTO c FROM table (see the comment into the procedure's code).
How to repeat:
create the following database:
CREATE DATABASE gestione;
USE gestione;
CREATE TABLE class_category (
cc_id int8 not null primary key auto_increment,
cc_name varchar(255) not null,
cc_desc text not null,
INDEX cc_name_ind (cc_name)
) TYPE=InnoDB;
CREATE TABLE class (
cl_id int8 not null primary key auto_increment,
cl_category int8 not null,
cl_name varchar(255) not null,
cl_desc text not null,
INDEX cl_name_ind (cl_name),
INDEX cl_cat_ind (cl_category),
FOREIGN KEY (cl_category) REFERENCES class_category(cc_id)
ON DELETE RESTRICT
) TYPE=InnoDB;
CREATE TABLE mimetype (
mime_id int4 not null primary key auto_increment,
mime_name varchar(255) not null,
mime_encoding varchar(32) not null
) TYPE=InnoDB;
CREATE TABLE input_type (
it_id int4 not null primary key auto_increment,
it_name varchar(255) not null,
it_type varchar(255) not null,
INDEX it_name_type_ind (it_name, it_type)
) TYPE=InnoDB;
CREATE TABLE class_property (
cp_id int8 not null primary key auto_increment,
cp_class int8 not null,
cp_name varchar(255) not null,
cp_prompt varchar(255) not null,
cp_maxsize int8 not null,
cp_minsize int8 not null,
cp_mimetype int4 not null,
cp_input_type int4 not null,
INDEX cp_name_prompt_ind (cp_name, cp_prompt),
INDEX cp_class_ind (cp_class),
INDEX cp_mimetype_ind (cp_mimetype),
INDEX cp_inputtype_ind (cp_input_type),
FOREIGN KEY (cp_class) REFERENCES class(cl_id)
ON DELETE RESTRICT,
FOREIGN KEY (cp_mimetype) REFERENCES mimetype(mime_id)
ON DELETE RESTRICT,
FOREIGN KEY (cp_input_type) REFERENCES input_type(it_id)
ON DELETE RESTRICT
) TYPE=InnoDB;
CREATE TABLE object (
obj_id int8 not null primary key auto_increment,
obj_class int8 not null,
obj_name varchar(255) not null,
INDEX obj_name_ind (obj_name),
INDEX obj_class_ind (obj_class),
FOREIGN KEY (obj_class) REFERENCES class(cl_id)
ON DELETE RESTRICT
) TYPE=InnoDB;
CREATE TABLE object_property (
op_id int8 not null primary key auto_increment,
op_cp int8 not null,
op_type char(4) not null,
op_object int8 not null,
op_value_int8 int8,
op_value_int4 int4,
op_value_int2 int2,
op_value_int1 int1,
op_value_char varchar(255),
op_value_text text,
op_value_object int8,
INDEX op_type_ind (op_type),
INDEX op_obj_ind (op_object),
INDEX op_cp_ind (op_cp),
INDEX op_value_int8_ind (op_value_int8),
INDEX op_value_int4_ind (op_value_int4),
INDEX op_value_int2_ind (op_value_int2),
INDEX op_value_int1_ind (op_value_int1),
INDEX op_value_char_ind (op_value_char),
INDEX op_value_obj_ind (op_value_object),
FOREIGN KEY (op_cp) REFERENCES class_property (cp_id)
ON DELETE RESTRICT,
FOREIGN KEY (op_object) REFERENCES object (obj_id)
ON DELETE RESTRICT,
FOREIGN KEY (op_value_object) REFERENCES object (obj_id)
ON DELETE RESTRICT
) TYPE=InnoDB;
CREATE TABLE node (
no_id int8 NOT NULL PRIMARY KEY AUTO_INCREMENT,
no_parent int8 not null,
no_next int8 not null,
no_prev int8 not null,
no_ctime int8 not null, -- creation timestamp
no_mtime int8 not null, -- modification timestamp
no_object int8 not null,
INDEX no_object_ind (no_object),
INDEX no_parent_ind (no_parent),
INDEX no_next_ind (no_next),
INDEX no_prev_ind (no_prev),
FOREIGN KEY (no_object) REFERENCES object(obj_id)
ON DELETE RESTRICT
) TYPE=InnoDB;
... and the following stored procedures:
DELIMITER |
DROP PROCEDURE IF EXISTS OSNodeGet;
CREATE PROCEDURE OSNodeGet(id int8)
BEGIN
DECLARE objid INT8 DEFAULT 0;
DECLARE cp, c INT DEFAULT 0;
DECLARE done INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
DECLARE node_id, node_parent, node_next, node_prev, node_ctime,
node_mtime, object_id, obj_id, object_class,
class_id, class_cat, prop_mime_id,
prop_maxsize, prop_minsize INT8;
DECLARE class_name, class_desc, object_name, prop_name, prop_mime,
prop_encoding, prop_prompt TEXT;
DECLARE oprop_id, oprop_cp, oprop_int8, oprop_int4, oprop_int2,
oprop_int1, oprop_object INT8;
DECLARE oprop_type, oprop_char, oprop_text TEXT;
DECLARE curs CURSOR FOR SELECT op_id, op_type, op_cp,
op_value_int8,
op_value_int4,
op_value_int2,
op_value_int1,
op_value_char,
op_value_text,
op_value_object
FROM object_property
WHERE op_object = objid;
CREATE TEMPORARY TABLE nodeget
SELECT * FROM node WHERE no_id = id;
SELECT @objid:=no_object FROM nodeget;
SELECT @objid:=no_object FROM nodeget;
SELECT count(*) INTO c FROM nodeget;
SELECT c;
IF c > 0 AND @objid > 0 THEN
CREATE TEMPORARY TABLE obj_get
SELECT * FROM object,class WHERE obj_id=@objid AND
class.cl_id = obj_class;
SELECT * FROM obj_get;
SELECT no_id, no_parent, no_next, no_prev, no_ctime,
no_mtime, no_object, obj_id, obj_class, obj_name,
class.cl_id, class.cl_category, class.cl_name,
class.cl_desc
INTO
node_id, node_parent, node_next,
node_prev, node_ctime, node_mtime,
object_id, obj_id, object_class,
object_name, class_id, class_cat,
class_name, class_desc
FROM nodeget, obj_get, class
WHERE class.cl_id = obj_class;
SELECT no_id, no_parent, no_next, no_prev, no_ctime,
no_mtime, no_object, obj_id, obj_class, obj_name
FROM nodeget, obj_get;
CREATE TEMPORARY TABLE result (
node_id int4,
node_parent int4,
node_next int4,
node_prev int4,
node_ctime int4,
node_mtime int4,
object_id int4,
object_name text,
object_name text,
object_class text,
class_desc text,
property_type text,
property_name text,
property_prompt text,
property_value text,
property_mime text,
property_encoding text,
property_maxsize int4,
property_minsize int4
);
SELECT count(*) INTO cp FROM object_property WHERE op_object=@objid;
IF cp > 0 THEN
OPEN curs;
properties: REPEAT
FETCH curs INTO oprop_id, oprop_type, oprop_cp,
oprop_int8, oprop_int4, oprop_int2,
oprop_int1, oprop_char, oprop_text,
oprop_object;
CASE oprop_type
WHEN 'int8' THEN SET @prop_val=oprop_int8;
WHEN 'int4' THEN SET @prop_val=oprop_int4;
WHEN 'int2' THEN SET @prop_val=oprop_int2;
WHEN 'int1' THEN SET @prop_val=oprop_int1;
WHEN 'char' THEN SET @prop_val=oprop_char;
WHEN 'text' THEN SET @prop_val=oprop_int8;
WHEN 'obje' THEN SET @prop_val=oprop_object;
END CASE;
SELECT cp_name, cp_prompt, cp_maxsize, cp_minsize,
cp_mimetype INTO
prop_name, prop_prompt,
prop_maxsize, prop_minsize,
prop_mime_id FROM class_property
WHERE cp_id = oprop_cp;
SELECT mime_name, mime_encoding INTO prop_mime,
prop_encoding FROM mimetype
WHERE mime_id = prop_mime_id;
INSERT INTO result VALUES (
node_id,
node_parent,
node_next,
node_prev,
node_ctime,
node_mtime,
object_id,
object_name,
class_name,
class_desc,
oprop_type,
prop_name,
prop_prompt,
@prop_val,
prop_mime,
prop_encoding,
prop_maxsize,
prop_minsize
);
UNTIL done END REPEAT properties;
CLOSE curs;
ELSE
INSERT INTO result VALUES (
node_id,
node_parent,
node_next,
node_prev,
node_ctime,
node_mtime,
object_id,
object_name,
class_name,
class_desc,
oprop_type,
prop_name,
prop_prompt,
@prop_val,
prop_mime,
prop_encoding,
prop_maxsize,
prop_minsize);
END IF;
DROP TABLE nodeget;
DROP TABLE obj_get;
SELECT * FROM result;
DROP TABLE result;
END IF;
END|
DROP PROCEDURE IF EXISTS OSClassCategoryCreate;
CREATE PROCEDURE OSClassCategoryCreate(name varchar(255),
description text)
BEGIN
DECLARE id INT;
SET AUTOCOMMIT=0;
INSERT INTO class_category (cc_name, cc_desc)
VALUES (name, description);
SELECT LAST_INSERT_ID(cc_id) INTO id FROM class_category;
COMMIT;
SELECT * FROM class_category WHERE cc_id = id;
END|
DROP PROCEDURE IF EXISTS OSClassCreate;
CREATE PROCEDURE OSClassCreate(category int8, name varchar(255),
description text)
BEGIN
DECLARE id INT;
SET AUTOCOMMIT=0;
INSERT INTO class (cl_name, cl_desc, cl_category)
VALUES (name, description, category);
SELECT LAST_INSERT_ID(cl_id) INTO id FROM class;
COMMIT;
SELECT * FROM class WHERE cl_id = id;
END|
DROP PROCEDURE IF EXISTS OSObjectCreate;
CREATE PROCEDURE OSObjectCreate(class int8, name varchar(255))
BEGIN
DECLARE id INT;
SET AUTOCOMMIT=0;
INSERT INTO object (obj_class, obj_name) VALUES (class, name);
SELECT LAST_INSERT_ID(obj_id) INTO id FROM object;
COMMIT;
SELECT * FROM object WHERE obj_id = id;
END|
DROP PROCEDURE IF EXISTS OSNodeObjectCreate;
CREATE PROCEDURE OSNodeObjectCreate(parent int8, sibling int8,
sort enum('After', 'Before'), class int8, name varchar(255))
BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
DECLARE objid, nodeid INT8;
SET AUTOCOMMIT=0;
CALL OSObjectCreate(class, name);
SELECT LAST_INSERT_ID(obj_id) INTO objid FROM object;
CALL OSNodeCreate(parent, sibling, 'After', objid);
COMMIT;
END|
DROP PROCEDURE IF EXISTS OSNodeCreate;
CREATE PROCEDURE OSNodeCreate(parent int8, sibling int8,
sort enum('After', 'Before'), object int8)
BEGIN
DECLARE id, inplaceof INT DEFAULT 0;
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
SET AUTOCOMMIT=0;
IF sibling > 0 THEN
IF sort = 'After' THEN
SELECT no_next INTO inplaceof FROM node
WHERE no_id = sibling;
INSERT INTO node (no_parent, no_next, no_prev, no_ctime, no_object)
VALUES ( parent, inplaceof, sibling,
UNIX_TIMESTAMP(), object);
SELECT LAST_INSERT_ID(no_id) INTO id FROM node;
IF inplaceof > 0 THEN
UPDATE node SET no_prev = id WHERE
no_id = inplaceof;
END IF;
UPDATE node SET no_next = id WHERE no_id = sibling;
ELSEIF sort = 'Before' THEN
SELECT no_prev INTO inplaceof FROM node
WHERE no_id = sibling;
INSERT INTO node (no_parent, no_next, no_prev, no_ctime, no_object)
VALUES ( parent, sibling, inplaceof,
UNIX_TIMESTAMP(), object);
SELECT LAST_INSERT_ID(no_id) INTO id FROM node;
IF inplaceof > 0 THEN
UPDATE node SET no_next = id WHERE
no_id = inplaceof;
END IF;
UPDATE node SET no_prev = id WHERE no_id = sibling;
END IF;
ELSE
SELECT no_id INTO sibling
FROM node WHERE no_parent = parent AND no_next = 0;
INSERT INTO node (no_parent, no_next, no_prev, no_ctime,
no_object)
VALUES ( parent, 0, sibling, UNIX_TIMESTAMP(),
object);
SELECT LAST_INSERT_ID(no_id) INTO id FROM node;
END IF;
COMMIT;
SELECT * FROM node WHERE no_id = id;
END|
then executes the following statements:
call OSClassCategoryCreate('System', 'System classes');
call OSClassCreate(1, 'System', 'System class');
call OSNodeObjectCreate(0, 0, 'After', 1, 'Root');
call OSNodeGet(1);
for me the output is:
mysql> call OSNodeGet(1);
+-------------------+
| @objid:=no_object |
+-------------------+
| 1 |
+-------------------+
1 row in set, 2 warnings (0.03 sec)
+-------------------+
| @objid:=no_object |
+-------------------+
| 1 |
+-------------------+
1 row in set, 2 warnings (0.03 sec)
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql>
and this is the log in hostname.err:
Number of processes running now: 0
040217 17:39:12 mysqld restarted
040217 17:39:12 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files...
InnoDB: Restoring possible half-written data pages from the doublewrite
InnoDB: buffer...
040217 17:39:12 InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 393823.
InnoDB: Doing recovery: scanned up to log sequence number 0 393823
040217 17:39:12 InnoDB: Flushing modified pages from the buffer pool...
040217 17:39:12 InnoDB: Started; log sequence number 0 393823
/usr/local/mysql/bin/mysqld: ready for connections.
Version: '5.0.0-alpha-standard-log' socket: '/tmp/mysql.sock' port: 3306
mysqld got signal 11;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help diagnose
the problem, but since we have already crashed, something is definitely wrong
and this may fail.
key_buffer_size=268435456
read_buffer_size=1044480
max_used_connections=0
max_connections=100
threads_connected=1
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = 466543 K
bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
thd=0x86380f0
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...
Cannot determine thread, fp=0xbfe7e708, backtrace may not be correct.
Stack range sanity check OK, backtrace follows:
0x80880d3
0x82df1d8
0x8083715
0x807f6c6
0x80b9091
0x80ba542
0x80b757e
0x8095db2
0x812f85f
0x812f6a3
0x812e0e7
0x812e6b0
0x8099aa3
0x809afc9
0x8094a1f
0x809439a
0x8093aea
0x82dc98c
0x83124ca
New value of fp=(nil) failed sanity check, terminating stack trace!
Please read http://www.mysql.com/doc/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved
stack trace is much more helpful in diagnosing the problem, so please do
resolve it
Trying to get some variables.
Some pointers may be invalid and cause the dump to abort...
thd->query at 0x8641f80 = call OSNodeGet(1)
thd->thread_id=3
The manual page at http://www.mysql.com/doc/en/Crashing.html contains
information that should help you find out what is causing the crash.
resolve_stack_dump gives the following output:
server:/usr/local/mysql/data# resolve_stack_dump -s /tmp/mysqld.sym -n /tmp/mysql.stack | c++filt
0x80880d3 handle_segfault + 423
0x82df1d8 pthread_sighandler + 184
0x8083715 Protocol::send_fields(List<Item> *, unsigned int) + 781
0x807f6c6 select_send::send_fields(List<Item> &, unsigned int) + 46
0x80b9091 JOIN::exec(void) + 261
0x80ba542 mysql_select__FP3THDPPP4ItemP13st_table_listUiRt4List1Z4ItemP4ItemUiP8st_orderT7T5T7UlP13select_resultP18st_select_lex_unitP13s + 838
0x80b757e handle_select(THD *, st_lex *, select_result *) + 174
0x8095db2 mysql_execute_command(THD *) + 1454
0x812f85f sp_instr_stmt::exec_stmt(THD *, st_lex *) + 427
0x812f6a3 sp_instr_stmt::execute(THD *, unsigned int *) + 31
0x812e0e7 sp_head::execute(THD *) + 143
0x812e6b0 sp_head::execute_procedure(THD *, List<Item> *) + 708
0x8099aa3 mysql_execute_command(THD *) + 17055
0x809afc9 mysql_parse(THD *, char *, unsigned int) + 185
0x8094a1f dispatch_command(enum_server_command, THD *, char *, unsigned int) + 1659
0x809439a do_command(THD *) + 218
0x8093aea handle_one_connection + 602
0x82dc98c pthread_start_thread + 220
0x83124ca thread_start + 4
server:/usr/local/mysql/data#