1--source include/have_debug_sync.inc
2--source include/have_gtid.inc
3
4# Save the initial number of concurrent sessions
5--source include/count_sessions.inc
6
7--echo #
8--echo # BUG#21463167 - GTIDS: LOCK_OPEN DEADLOCK WITH REVOKE INCIDENT +
9--echo #                SHOW TABLE STATUS CONCURRENTLY
10--echo #
11
12CREATE USER u1;
13CREATE TABLE t1(a INT);
14CREATE VIEW v1 AS SELECT * FROM t1;
15
16CALL mtr.add_suppression("REVOKE failed while revoking all_privileges from a list of users.");
17
18--enable_connect_log
19
20--connect (con1, localhost, root,,)
21# Set force_mysql_revoke_all_fail in order to simulate partial execution failure
22# in mysql_revoke_all(). In this case execution flow go to the 'if' branch where
23# mysql_bin_log.write_incident is called.
24SET debug="+d,force_mysql_revoke_all_fail";
25# When the sync point revoke_all_before_write_incident_to_binlog
26# will be hit a write lock for LOCK_grant has already been acquired
27# in mysql_revoke_all() and we are waiting for the signal revoke_all_cont
28# be emitted to go inside mysql_bin_log.write_incident() where LOCK_open
29# will be acquired.
30SET DEBUG_SYNC='revoke_all_before_write_incident_to_binlog SIGNAL revoke_all_has_lock_grant WAIT_FOR revoke_all_cont';
31
32--connection default
33# Set the debug variable force_check_table_access_return_ok
34# in order to avoid calling of check_grant as part of handling
35# the statement SET DEBUG_SYNC="....". If we didn't do so we would be suspended on
36# waiting for LOCK_grant be released that had been acquired on handling REVOKE ALL.
37SET debug="+d,force_check_table_access_return_ok";
38
39--connection con1
40# Processing of the following REVOKE ALL will be suspended on
41# the sync point revoke_all_before_write_incident_to_binlog waiting until
42# the signal revoke_all_cont be emitted. While suspending it holds
43# the lock LOCK_grant on write.
44--echo # Sending REVOKE ALL PRIVILEGES
45--send REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'u1'@'%'
46
47--connection default
48# In the default connection we are waiting until processing of the statement
49# REVOKE ALL PRIVILEGES hit the sync point revoke_all_before_write_incident_to_binlog.
50# When this happen the connection con1 holds LOCK_grant on write.
51SET DEBUG_SYNC='now WAIT_FOR revoke_all_has_lock_grant';
52
53# When processing the statement SHOW TABLE STATUS we will hit the sync point
54# fill_effective_table_privileges that will emit signal revoke_all_cont.
55# At this point we know that REVOKE ALL PRIVILEGES has already acquired LOCK_grant.
56# Waken up thread that is handling REVOKE ALL PRIVILEGES will try to acquire
57# LOCK_open while executing mysql_bin_log.write_incident().
58SET DEBUG_SYNC='fill_effective_table_privileges SIGNAL revoke_all_cont';
59
60--replace_column 12 x
61# When there is a view while handling SHOW TABLE STATUS the function mysql_make_view()
62# is called from open_table(). LOCK_open has been acquired within open_table before calling
63# mysql_make_view and when we are trying to lock LOCK_grant on read from
64# revoke_all_before_write_incident_to_binlog we would get a deadlock without the patch.
65SHOW TABLE STATUS;
66
67--connection con1
68# Get execution result of REVOKE ALL PRIVILEGES.
69# We expect the error ER_REVOKE_GRANTS since the debug variable force_mysql_revoke_all_fail
70# was set to simulate failure of REVOKE ALL PRIVILEGES
71--echo # Reaping REVOKE ALL PRIVILEGES
72--error ER_REVOKE_GRANTS
73--reap
74
75--connection default
76--disconnect con1
77DROP USER u1;
78DROP VIEW v1;
79DROP TABLE t1;
80# Wait till we reached the initial number of concurrent sessions
81--source include/wait_until_count_sessions.inc
82--disable_connect_log
83
84SET debug='';
85
86