diff options
Diffstat (limited to 'apps/plugin.c')
| -rw-r--r-- | apps/plugin.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index a1ffa3a..0d4d8ed 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -63,6 +63,15 @@ #define PREFIX #endif +#if defined(HAVE_PLUGIN_CHECK_OPEN_CLOSE) && (MAX_OPEN_FILES>32) +#warning "MAX_OPEN_FILES>32, disabling plugin file open/close checking" +#undef HAVE_PLUGIN_CHECK_OPEN_CLOSE +#endif + +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE +static unsigned int open_files; +#endif + #ifdef SIMULATOR static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; void *sim_plugin_load(char *plugin, void **pd); @@ -83,6 +92,13 @@ static char current_plugin[MAX_PATH]; char *plugin_get_current_filename(void); +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE +/* Some wrappers used to monitor open and close and detect leaks*/ +static int open_wrapper(const char* pathname, int flags); +static int close_wrapper(int fd); +static int creat_wrapper(const char *pathname); +#endif + static const struct plugin_api rockbox_api = { /* lcd */ @@ -276,11 +292,20 @@ static const struct plugin_api rockbox_api = { #endif /* HAVE_BUTTON_LIGHT */ /* file */ +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE + (open_func)open_wrapper, + close_wrapper, +#else (open_func)PREFIX(open), PREFIX(close), + #endif (read_func)PREFIX(read), PREFIX(lseek), +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE + (creat_func)creat_wrapper, +#else (creat_func)PREFIX(creat), +#endif (write_func)PREFIX(write), PREFIX(remove), PREFIX(rename), @@ -805,8 +830,12 @@ int plugin_load(const char* plugin, const void* parameter) touchscreen_set_mode(TOUCHSCREEN_BUTTON); #endif +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE + open_files = 0; +#endif + rc = hdr->entry_point(parameter); - + /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); @@ -850,6 +879,25 @@ int plugin_load(const char* plugin, const void* parameter) if (pfn_tsr_exit == NULL) plugin_loaded = false; +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE + if(open_files != 0 && !plugin_loaded) + { + int fd; + logf("Plugin '%s' leaks file handles", plugin); + + static const char *lines[] = + { ID2P(LANG_PLUGIN_ERROR), + "#leak-file-handles" }; + static const struct text_message message={ lines, 2 }; + button_clear_queue(); /* Empty the keyboard buffer */ + gui_syncyesno_run(&message, NULL, NULL); + + for(fd=0; fd < MAX_OPEN_FILES; fd++) + if(open_files & (1<<fd)) + close_wrapper(fd); + } +#endif + sim_plugin_close(pd); if (rc == PLUGIN_ERROR) @@ -926,3 +974,37 @@ char *plugin_get_current_filename(void) { return current_plugin; } + +#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE +static int open_wrapper(const char* pathname, int flags) +{ + int fd = PREFIX(open)(pathname,flags); + + if(fd >= 0) + open_files |= 1<<fd; + + return fd; +} + +static int close_wrapper(int fd) +{ + if((~open_files) & (1<<fd)) + { + logf("double close from plugin"); + } + if(fd >= 0) + open_files &= (~(1<<fd)); + + return PREFIX(close)(fd); +} + +static int creat_wrapper(const char *pathname) +{ + int fd = PREFIX(creat)(pathname); + + if(fd >= 0) + open_files |= (1<<fd); + + return fd; +} +#endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */ |