@@ -80,47 +80,86 @@ def test_busy_timeout
8080 assert time . real *1000 >= 1000
8181 end
8282
83- def test_busy_timeout_blocks_gvl
84- threads = [ 1 , 2 ] . map do
85- Thread . new do
86- begin
87- db = SQLite3 ::Database . new ( "test.db" )
88- db . busy_timeout = 3000
89- db . transaction ( :immediate ) do
90- db . execute "insert into foo ( b ) values ( ? )" , rand ( 1000 ) . to_s
91- sleep 1
92- db . execute "insert into foo ( b ) values ( ? )" , rand ( 1000 ) . to_s
93- end
94- ensure
95- db . close if db
83+ def test_busy_timeout_holds_gvl
84+ work = [ ]
85+ Thread . new do
86+ while true
87+ sleep 0.1
88+ work << '.'
89+ end
90+ end
91+ sleep 1
92+
93+ @db . busy_timeout 1000
94+ busy = Mutex . new
95+ busy . lock
96+
97+ t = Thread . new do
98+ begin
99+ db2 = SQLite3 ::Database . open ( "test.db" )
100+ db2 . transaction ( :exclusive ) do
101+ busy . lock
96102 end
103+ ensure
104+ db2 . close if db2
97105 end
98106 end
107+ sleep 1
99108
100- assert_raise ( SQLite3 ::BusyException ) do
101- threads . each ( &:join )
109+ assert_raises ( SQLite3 ::BusyException ) do
110+ work << '>'
111+ @db . execute "insert into foo (b) values ( 'from 2' )"
102112 end
113+
114+ busy . unlock
115+ t . join
116+
117+ assert 2 == work . size - work . find_index ( ">" )
103118 end
104119
105120 def test_busy_handler_timeout_releases_gvl
106- threads = [ 1 , 2 ] . map do
107- Thread . new do
108- begin
109- db = SQLite3 ::Database . new ( "test.db" )
110- db . busy_handler_timeout = 3000
111- db . transaction ( :immediate ) do
112- db . execute "insert into foo ( b ) values ( ? )" , rand ( 1000 ) . to_s
113- sleep 1
114- db . execute "insert into foo ( b ) values ( ? )" , rand ( 1000 ) . to_s
115- end
116- ensure
117- db . close if db
121+ work = [ ]
122+
123+ Thread . new do
124+ while true
125+ sleep 0.1
126+ work << '.'
127+ end
128+ end
129+
130+ @db . busy_handler do |count |
131+ now = Process . clock_gettime ( Process ::CLOCK_MONOTONIC )
132+ if count . zero?
133+ @timeout_deadline = now + 1
134+ elsif now > @timeout_deadline
135+ next false
136+ else
137+ sleep ( 0.001 )
138+ end
139+ end
140+ busy = Mutex . new
141+ busy . lock
142+
143+ t = Thread . new do
144+ begin
145+ db2 = SQLite3 ::Database . open ( "test.db" )
146+ db2 . transaction ( :exclusive ) do
147+ busy . lock
118148 end
149+ ensure
150+ db2 . close if db2
119151 end
120152 end
153+ sleep 1
121154
122- assert_nothing_raised do
123- threads . each ( &:join )
155+ assert_raises ( SQLite3 ::BusyException ) do
156+ work << '>'
157+ @db . execute "insert into foo (b) values ( 'from 2' )"
124158 end
159+
160+ busy . unlock
161+ t . join
162+
163+ assert 2 < work . size - work . find_index ( ">" )
125164 end
126165end
0 commit comments