Commit FS#10889: detect file handles leaks in plugins and automatically close them on exit and warn the user.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24598 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
552a54d87f
commit
e5caf93e23
2 changed files with 89 additions and 1 deletions
|
@ -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 */
|
||||
|
|
|
@ -908,5 +908,11 @@ Lyre prototype 1 */
|
|||
#define STORAGE_ALIGN_MASK 0
|
||||
#endif
|
||||
|
||||
/* This attribute can be used to enable to detection of plugin file handles leaks.
|
||||
* When enabled, the plugin core will monitor open/close/creat and when the plugin exits
|
||||
* will display an error message if the plugin leaked some file handles */
|
||||
#ifndef SIMULATOR
|
||||
#define HAVE_PLUGIN_CHECK_OPEN_CLOSE
|
||||
#endif
|
||||
|
||||
#endif /* __CONFIG_H__ */
|
||||
|
|
Loading…
Reference in a new issue