From: Martin Friebe Date: December 10 2007 8:34pm Subject: Re: Proposal for a Test Synchronization Facility List-Archive: http://lists.mysql.com/internals/35220 Message-Id: <475DA2DE.3000300@hybyte.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Nice, Just a thought, something very similar can be archived using named-locks "get_lock('name', timeout)". And for easier use in testcases the testsuite could provide macros, do call the functions. 1) sending a signal, if you have done something: do get_lock('mysql_after_sync_insert:inserted', 1'); and check for it with select is_free_lock('mysql_after_sync_insert:inserted'); 1a) if you want to avoid that the process waiting for the "signal" has to poll all the time then you do this: p1 => process that will send p2 => process that should wait # prepare p1: do get_lock('name : not_yet_send', 1); #work (next 2 lines in any order) p1: #do some work p2: do get_lock('name : not_yet_send', 999999999'); # wait "forever" # send p1: do release_lock('name : not_yet_send', 1'); p2 #returns, and know the signal is send 1b) if you wish to recognize that p1 did not die/crash, which would release the lock, and send a false signal #prepare p1: do get_lock('name : not_yet_send', 1); #work p1: #do some work p2: do get_lock('name : not_yet_send', 999999999'); # wait "forever" #send p1: do get_lock('name : now_send', 1); # send the signal p1: do release_lock('name : not_yet_send', 1'); p2 #returns p2 select is_used_lock('name : now_send'); # only true if p1 did not die 2) In the same way, p2 could have gotten a lock, which p1 could then wait for, after p1 did send the signal. The only back draw is: you have to know in advance, which process will listen for the signal 3) Of course the above syntax is too complex, but the testsuite could provide some macros to archive this. #prepare p1: prepare_signal('name') #select get_lock('name : not_yet_send', 1); => selftest: must return 1 #work (in any order) p1: #do some work p2: wait_for_signal('name'); # do get_lock('name : not_yet_send', 999999); select get_lock('name : now_send'); # select must return 1 #send p1: send_signal(name); # do get_lock('name : now_send', 1); do release_lock('name : not_yet_send', 1'); p2 #returns and has checked the result of get_lock 4) p1 should first send, and then wait p1: prepare_signal('name'); p2: prepare_signal('response'); # p1 work p2 wait_for_signal('name') # send p1: send_signal(name); p1: wait_for_signal('response') # already prepared, so will wait # work in p2 p2 # work p2: send_signal(response); # p1 continues Also in this case, the macros could do more. Instead of "do get_lock('name',1)", with a smal ltimeout, when you expect the lock to be free, it could do "select get_lock('name', 1);" and check the result (must be 1). Of course get_lock('name : not_yet_send', 999999999'); # wait "forever" is not fail-safe. After 99999999 seconds the test could return a false positive. But IMHO for real world, this is quite ignorable. The advantage is that no changes to the server are needed. So it culd be used with current GA servers immediately. Martin Ingo Strüwing wrote: > Hi! > > Herewith I propose a new facility to be used in the test suite to make > race conditions repeatable and get rid of sleeps. > > The facility is controlled by user variables. For example, if you have a > "synchronization point" in the code like this: > > MYSQL_TEST_SYNC(thd, "mysql_test_sync_after_insert"); > > then you can control it by a user variable in the test case like so: > > SET @mysql_test_sync_after_insert= 'inserted:flushed'; > > When the code execution in a thread reaches the synchronization point, > it "sends" the 'inserted' signal (it sets a global String to "inserted" > and broadcasts a global condition). Then the thread waits until another > thread sends the 'flushed' signal (sets the global String to "flushed" > and broadcasts the global condition). > > The patch http://lists.mysql.com/commits/39659 contains the main part > and documentation in item_func.cc. It does also contain functions for > convenient access to user variable values, an example test case with > changes to show how to use the facility, and synchronization points used > by the changed test case. It removes some sleeps and could reduce test > case execution time from 7 seconds to 0.4 seconds. > > Please send me your thoughts. Do you think we should include it in the > MySQL code? > > Regards > Ingo >