cgen: fix deadlock when returning multiple values in lock (#14014)
							parent
							
								
									3e3b2e25db
								
							
						
					
					
						commit
						afb07e0e16
					
				| 
						 | 
					@ -3902,6 +3902,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
 | 
				
			||||||
	tmpvar := g.new_tmp_var()
 | 
						tmpvar := g.new_tmp_var()
 | 
				
			||||||
	ret_typ := g.typ(g.unwrap_generic(g.fn_decl.return_type))
 | 
						ret_typ := g.typ(g.unwrap_generic(g.fn_decl.return_type))
 | 
				
			||||||
	mut use_tmp_var := g.defer_stmts.len > 0 || g.defer_profile_code.len > 0
 | 
						mut use_tmp_var := g.defer_stmts.len > 0 || g.defer_profile_code.len > 0
 | 
				
			||||||
 | 
							|| g.cur_lock.lockeds.len > 0
 | 
				
			||||||
	// handle promoting none/error/function returning 'Option'
 | 
						// handle promoting none/error/function returning 'Option'
 | 
				
			||||||
	if fn_return_is_optional {
 | 
						if fn_return_is_optional {
 | 
				
			||||||
		optional_none := node.exprs[0] is ast.None
 | 
							optional_none := node.exprs[0] is ast.None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
// vtest retry: 3
 | 
					 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct AA {
 | 
					struct AA {
 | 
				
			||||||
| 
						 | 
					@ -6,49 +5,42 @@ mut:
 | 
				
			||||||
	b string
 | 
						b string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	run_time   = time.millisecond * 200 // must be big enough to ensure threads have started
 | 
					 | 
				
			||||||
	sleep_time = time.millisecond * 250 // some tolerance added
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn test_return_lock() {
 | 
					fn test_return_lock() {
 | 
				
			||||||
	start := time.now()
 | 
						start := time.now()
 | 
				
			||||||
	shared s := AA{'3'}
 | 
						shared s := AA{'3'}
 | 
				
			||||||
	go printer(shared s, start)
 | 
						reader(shared s)
 | 
				
			||||||
	go fn (shared s AA, start time.Time) {
 | 
						lock s {
 | 
				
			||||||
		for {
 | 
							assert s.b == '5'
 | 
				
			||||||
			reader(shared s)
 | 
							s.b = '4'
 | 
				
			||||||
			if time.now() - start > run_time {
 | 
						}
 | 
				
			||||||
				exit(0)
 | 
						rlock s {
 | 
				
			||||||
			}
 | 
							assert s.b == '4'
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}(shared s, start)
 | 
					 | 
				
			||||||
	time.sleep(sleep_time)
 | 
					 | 
				
			||||||
	assert false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn printer(shared s AA, start time.Time) {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		lock s {
 | 
					 | 
				
			||||||
			assert s.b in ['0', '1', '2', '3', '4', '5']
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if time.now() - start > run_time {
 | 
					 | 
				
			||||||
			exit(0)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn reader(shared s AA) {
 | 
					fn reader(shared s AA) {
 | 
				
			||||||
	mut i := 0
 | 
						lock s {
 | 
				
			||||||
	for {
 | 
							assert s.b == '3'
 | 
				
			||||||
		i++
 | 
							s.b = '5'
 | 
				
			||||||
		x := i.str()
 | 
							// this test checks if cgen unlocks the mutex here
 | 
				
			||||||
		lock s {
 | 
							return
 | 
				
			||||||
			s.b = x
 | 
					 | 
				
			||||||
			if s.b == '5' {
 | 
					 | 
				
			||||||
				// this test checks if cgen unlocks the mutex here
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_multi_return_lock() {
 | 
				
			||||||
 | 
						shared s := AA{'3'}
 | 
				
			||||||
 | 
						reti, retb := printer2(shared s)
 | 
				
			||||||
 | 
						lock s {
 | 
				
			||||||
 | 
							assert s.b == '3'
 | 
				
			||||||
 | 
							assert reti == 4
 | 
				
			||||||
 | 
							assert retb == true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn printer2(shared s AA) (int, bool) {
 | 
				
			||||||
 | 
						rlock s {
 | 
				
			||||||
 | 
							assert s.b == '3'
 | 
				
			||||||
 | 
							return 4, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 5, false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue