diff --git a/src/common.h b/src/common.h index 73de4b78..0b429d45 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 30 +#define IRSSI_ABI_VERSION 31 #define DEFAULT_SERVER_ADD_PORT 6667 #define DEFAULT_SERVER_ADD_TLS_PORT 6697 diff --git a/src/perl/perl-core.c b/src/perl/perl-core.c index 866b86e8..24f0218c 100644 --- a/src/perl/perl-core.c +++ b/src/perl/perl-core.c @@ -65,10 +65,6 @@ static void perl_script_destroy_package(PERL_SCRIPT_REC *script) static void perl_script_destroy(PERL_SCRIPT_REC *script) { - perl_scripts = g_slist_remove(perl_scripts, script); - - perl_signal_remove_script(script); - perl_source_remove_script(script); signal_emit("script destroyed", 1, script); @@ -277,6 +273,7 @@ static PERL_SCRIPT_REC *script_load(char *name, const char *path, script->package = g_strdup_printf("Irssi::Script::%s", name); script->path = g_strdup(path); script->data = g_strdup(data); + script->refcount = 1; perl_scripts = g_slist_append(perl_scripts, script); signal_emit("script created", 1, script); @@ -311,10 +308,37 @@ PERL_SCRIPT_REC *perl_script_load_data(const char *data) /* Unload perl script */ void perl_script_unload(PERL_SCRIPT_REC *script) { - g_return_if_fail(script != NULL); + GSList *link; + g_return_if_fail(script != NULL); perl_script_destroy_package(script); - perl_script_destroy(script); + + perl_signal_remove_script(script); + perl_source_remove_script(script); + + link = g_slist_find(perl_scripts, script); + if (link != NULL) { + perl_scripts = g_slist_remove_link(perl_scripts, link); + g_slist_free(link); + perl_script_unref(script); + } +} + +/* Enter a perl script (signal or input source) */ +void perl_script_ref(PERL_SCRIPT_REC *script) +{ + g_return_if_fail(script != NULL); + + script->refcount++; +} + +void perl_script_unref(PERL_SCRIPT_REC *script) +{ + g_return_if_fail(script != NULL); + + script->refcount--; + if (!script->refcount) + perl_script_destroy(script); } /* Find loaded script by name */ diff --git a/src/perl/perl-core.h b/src/perl/perl-core.h index 0d3a1a2f..6ea637ae 100644 --- a/src/perl/perl-core.h +++ b/src/perl/perl-core.h @@ -8,6 +8,7 @@ typedef struct { /* Script can be loaded from a file, or from some data in memory */ char *path; /* FILE: full path for file */ char *data; /* DATA: data used for the script */ + int refcount; /* 0 = destroy */ } PERL_SCRIPT_REC; extern GSList *perl_scripts; @@ -26,6 +27,11 @@ PERL_SCRIPT_REC *perl_script_load_data(const char *data); /* Unload perl script */ void perl_script_unload(PERL_SCRIPT_REC *script); +/* Mark a script as entered */ +void perl_script_ref(PERL_SCRIPT_REC *script); +/* Mark a script as exited */ +void perl_script_unref(PERL_SCRIPT_REC *script); + /* Find loaded script by name */ PERL_SCRIPT_REC *perl_script_find(const char *name); /* Find loaded script by package */ diff --git a/src/perl/perl-signals.c b/src/perl/perl-signals.c index 27522f5e..f5f9d6e2 100644 --- a/src/perl/perl-signals.c +++ b/src/perl/perl-signals.c @@ -414,13 +414,17 @@ static void sig_func(const void *p1, const void *p2, const void *p5, const void *p6) { PERL_SIGNAL_REC *rec; + PERL_SCRIPT_REC *script; const void *args[SIGNAL_MAX_ARGUMENTS]; args[0] = p1; args[1] = p2; args[2] = p3; args[3] = p4; args[4] = p5; args[5] = p6; rec = signal_get_user_data(); - perl_call_signal(rec->script, rec->func, signal_get_emitted_id(), args); + script = rec->script; + perl_script_ref(script); + perl_call_signal(script, rec->func, signal_get_emitted_id(), args); + perl_script_unref(script); } static void perl_signal_add_full_int(const char *signal, SV *func, diff --git a/src/perl/perl-sources.c b/src/perl/perl-sources.c index 3c72be22..69d86f1f 100644 --- a/src/perl/perl-sources.c +++ b/src/perl/perl-sources.c @@ -78,6 +78,7 @@ static int perl_source_event(PERL_SOURCE_REC *rec) PUTBACK; perl_source_ref(rec); + perl_script_ref(rec->script); perl_call_sv(rec->func, G_EVAL|G_DISCARD); if (SvTRUE(ERRSV)) { @@ -86,6 +87,8 @@ static int perl_source_event(PERL_SOURCE_REC *rec) g_free(error); } + perl_script_unref(rec->script); + if (perl_source_unref(rec) && rec->once) perl_source_destroy(rec);