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) {
|
||||||
//v -o bounce -shared bounce.v
|
|
||||||
os__system(tos2("$vexe -o $file_base -shared $file"));
|
|
||||||
last = now;
|
last = now;
|
||||||
|
|
||||||
|
//v -o bounce -shared bounce.v
|
||||||
|
lfnmutex_print("compiling tmp.${file_base} ...");
|
||||||
|
os__system(tos2("$vexe -o tmp.${file_base} -shared $file"));
|
||||||
|
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");
|
load_so("$so_name");
|
||||||
|
lfnmutex_print("loaded ${so_name}");
|
||||||
}
|
}
|
||||||
time__sleep_ms(400);
|
|
||||||
|
lfnmutex_print("reload_so unlocking...");
|
||||||
|
pthread_mutex_unlock(&live_fn_mutex);
|
||||||
|
lfnmutex_print("reload_so unlocked");
|
||||||
|
|
||||||
|
_live_reloads++;
|
||||||
|
}
|
||||||
|
time__sleep_ms(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
' )
|
' )
|
||||||
|
|
Loading…
Reference in New Issue