live reload: fix SIGSEGV when calling dlclose, while a live fn is still running.
							parent
							
								
									913cd2ede4
								
							
						
					
					
						commit
						a65ae726ee
					
				| 
						 | 
					@ -344,6 +344,12 @@ fn (p mut Parser) fn_decl() {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.attr == 'live' && p.pref.is_so {
 | 
				
			||||||
 | 
							//p.genln('// live_function body start')
 | 
				
			||||||
 | 
							p.genln('pthread_mutex_lock(&live_fn_mutex);')
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if f.name == 'main' || f.name == 'WinMain' {
 | 
						if f.name == 'main' || f.name == 'WinMain' {
 | 
				
			||||||
		p.genln('init_consts();')
 | 
							p.genln('init_consts();')
 | 
				
			||||||
		if p.table.imports.contains('os') {
 | 
							if p.table.imports.contains('os') {
 | 
				
			||||||
| 
						 | 
					@ -388,6 +394,12 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
 | 
				
			||||||
	if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' {
 | 
						if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' {
 | 
				
			||||||
		p.error('$f.name must return "$typ"')
 | 
							p.error('$f.name must return "$typ"')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if p.attr == 'live' && p.pref.is_so {
 | 
				
			||||||
 | 
							//p.genln('// live_function body end')
 | 
				
			||||||
 | 
							p.genln('pthread_mutex_unlock(&live_fn_mutex);')
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	// {} closed correctly? scope_level should be 0
 | 
						// {} closed correctly? scope_level should be 0
 | 
				
			||||||
	if p.mod == 'main' {
 | 
						if p.mod == 'main' {
 | 
				
			||||||
		// println(p.cur_fn.scope_level)
 | 
							// println(p.cur_fn.scope_level)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -252,6 +252,14 @@ byteptr g_str_buf;
 | 
				
			||||||
int load_so(byteptr);
 | 
					int load_so(byteptr);
 | 
				
			||||||
void reload_so();
 | 
					void reload_so();
 | 
				
			||||||
void init_consts();')
 | 
					void init_consts();')
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if v.pref.is_so {
 | 
				
			||||||
 | 
							cgen.genln('extern pthread_mutex_t live_fn_mutex;')
 | 
				
			||||||
 | 
						}  
 | 
				
			||||||
 | 
						if v.pref.is_live {
 | 
				
			||||||
 | 
							cgen.genln('pthread_mutex_t live_fn_mutex = PTHREAD_MUTEX_INITIALIZER;')
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	imports_json := v.table.imports.contains('json')
 | 
						imports_json := v.table.imports.contains('json')
 | 
				
			||||||
	// TODO remove global UI hack
 | 
						// TODO remove global UI hack
 | 
				
			||||||
	if v.os == .mac && ((v.pref.build_mode == .embed_vlib && v.table.imports.contains('ui')) ||
 | 
						if v.os == .mac && ((v.pref.build_mode == .embed_vlib && v.table.imports.contains('ui')) ||
 | 
				
			||||||
| 
						 | 
					@ -388,6 +396,15 @@ string _STR_TMP(const char *fmt, ...) {
 | 
				
			||||||
		vexe := os.args[0] 
 | 
							vexe := os.args[0] 
 | 
				
			||||||
		os.system('$vexe -o $file_base -shared $file') 
 | 
							os.system('$vexe -o $file_base -shared $file') 
 | 
				
			||||||
		cgen.genln('
 | 
							cgen.genln('
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void lfnmutex_print(char *s){
 | 
				
			||||||
 | 
						if(0){
 | 
				
			||||||
 | 
							fflush(stderr);
 | 
				
			||||||
 | 
							fprintf(stderr,">> live_fn_mutex: %p | %s\\n", &live_fn_mutex, s);
 | 
				
			||||||
 | 
							fflush(stderr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <dlfcn.h>
 | 
					#include <dlfcn.h>
 | 
				
			||||||
void* live_lib; 
 | 
					void* live_lib; 
 | 
				
			||||||
int load_so(byteptr path) {
 | 
					int load_so(byteptr path) {
 | 
				
			||||||
| 
						 | 
					@ -401,20 +418,40 @@ int load_so(byteptr path) {
 | 
				
			||||||
		for so_fn in cgen.so_fns {
 | 
							for so_fn in cgen.so_fns {
 | 
				
			||||||
			cgen.genln('$so_fn = dlsym(live_lib, "$so_fn");  ')
 | 
								cgen.genln('$so_fn = dlsym(live_lib, "$so_fn");  ')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		cgen.genln('return 1; }
 | 
							
 | 
				
			||||||
 
 | 
							cgen.genln('return 1; 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int _live_reloads = 0;
 | 
				
			||||||
void reload_so() {
 | 
					void reload_so() {
 | 
				
			||||||
	int last = os__file_last_mod_unix(tos2("$file"));
 | 
						int last = os__file_last_mod_unix(tos2("$file"));
 | 
				
			||||||
	while (1) {
 | 
						while (1) {
 | 
				
			||||||
		// TODO use inotify 
 | 
							// TODO use inotify 
 | 
				
			||||||
		int now = os__file_last_mod_unix(tos2("$file")); 
 | 
							int now = os__file_last_mod_unix(tos2("$file")); 
 | 
				
			||||||
		if (now != last) {
 | 
							if (now != last) {
 | 
				
			||||||
 | 
								last = now;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			//v -o bounce -shared bounce.v 
 | 
								//v -o bounce -shared bounce.v 
 | 
				
			||||||
			os__system(tos2("$vexe -o $file_base -shared $file")); 
 | 
								lfnmutex_print("compiling tmp.${file_base} ...");
 | 
				
			||||||
			last = now; 
 | 
								os__system(tos2("$vexe -o tmp.${file_base} -shared $file"));
 | 
				
			||||||
			load_so("$so_name"); 
 | 
								lfnmutex_print("tmp.${file_base}.so compiled. reloading ...");      			
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								lfnmutex_print("reload_so locking...");    
 | 
				
			||||||
 | 
								pthread_mutex_lock(&live_fn_mutex);    
 | 
				
			||||||
 | 
								lfnmutex_print("reload_so locked");
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								if(0 == rename("tmp.${file_base}.so", "${so_name}")){
 | 
				
			||||||
 | 
									load_so("$so_name");
 | 
				
			||||||
 | 
									lfnmutex_print("loaded ${so_name}");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								lfnmutex_print("reload_so unlocking...");  
 | 
				
			||||||
 | 
								pthread_mutex_unlock(&live_fn_mutex);  
 | 
				
			||||||
 | 
								lfnmutex_print("reload_so unlocked");
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
								_live_reloads++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		time__sleep_ms(400); 
 | 
							time__sleep_ms(100); 
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
' ) 
 | 
					' ) 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue