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 a1ffa3abe1..0d4d8ed0f6 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -63,6 +63,15 @@ | |||
63 | #define PREFIX | 63 | #define PREFIX |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | #if defined(HAVE_PLUGIN_CHECK_OPEN_CLOSE) && (MAX_OPEN_FILES>32) | ||
67 | #warning "MAX_OPEN_FILES>32, disabling plugin file open/close checking" | ||
68 | #undef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
69 | #endif | ||
70 | |||
71 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
72 | static unsigned int open_files; | ||
73 | #endif | ||
74 | |||
66 | #ifdef SIMULATOR | 75 | #ifdef SIMULATOR |
67 | static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; | 76 | static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; |
68 | void *sim_plugin_load(char *plugin, void **pd); | 77 | void *sim_plugin_load(char *plugin, void **pd); |
@@ -83,6 +92,13 @@ static char current_plugin[MAX_PATH]; | |||
83 | 92 | ||
84 | char *plugin_get_current_filename(void); | 93 | char *plugin_get_current_filename(void); |
85 | 94 | ||
95 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
96 | /* Some wrappers used to monitor open and close and detect leaks*/ | ||
97 | static int open_wrapper(const char* pathname, int flags); | ||
98 | static int close_wrapper(int fd); | ||
99 | static int creat_wrapper(const char *pathname); | ||
100 | #endif | ||
101 | |||
86 | static const struct plugin_api rockbox_api = { | 102 | static const struct plugin_api rockbox_api = { |
87 | 103 | ||
88 | /* lcd */ | 104 | /* lcd */ |
@@ -276,11 +292,20 @@ static const struct plugin_api rockbox_api = { | |||
276 | #endif /* HAVE_BUTTON_LIGHT */ | 292 | #endif /* HAVE_BUTTON_LIGHT */ |
277 | 293 | ||
278 | /* file */ | 294 | /* file */ |
295 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
296 | (open_func)open_wrapper, | ||
297 | close_wrapper, | ||
298 | #else | ||
279 | (open_func)PREFIX(open), | 299 | (open_func)PREFIX(open), |
280 | PREFIX(close), | 300 | PREFIX(close), |
301 | #endif | ||
281 | (read_func)PREFIX(read), | 302 | (read_func)PREFIX(read), |
282 | PREFIX(lseek), | 303 | PREFIX(lseek), |
304 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
305 | (creat_func)creat_wrapper, | ||
306 | #else | ||
283 | (creat_func)PREFIX(creat), | 307 | (creat_func)PREFIX(creat), |
308 | #endif | ||
284 | (write_func)PREFIX(write), | 309 | (write_func)PREFIX(write), |
285 | PREFIX(remove), | 310 | PREFIX(remove), |
286 | PREFIX(rename), | 311 | PREFIX(rename), |
@@ -805,8 +830,12 @@ int plugin_load(const char* plugin, const void* parameter) | |||
805 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); | 830 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); |
806 | #endif | 831 | #endif |
807 | 832 | ||
833 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
834 | open_files = 0; | ||
835 | #endif | ||
836 | |||
808 | rc = hdr->entry_point(parameter); | 837 | rc = hdr->entry_point(parameter); |
809 | 838 | ||
810 | /* Go back to the global setting in case the plugin changed it */ | 839 | /* Go back to the global setting in case the plugin changed it */ |
811 | #ifdef HAVE_TOUCHSCREEN | 840 | #ifdef HAVE_TOUCHSCREEN |
812 | touchscreen_set_mode(global_settings.touch_mode); | 841 | touchscreen_set_mode(global_settings.touch_mode); |
@@ -850,6 +879,25 @@ int plugin_load(const char* plugin, const void* parameter) | |||
850 | if (pfn_tsr_exit == NULL) | 879 | if (pfn_tsr_exit == NULL) |
851 | plugin_loaded = false; | 880 | plugin_loaded = false; |
852 | 881 | ||
882 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
883 | if(open_files != 0 && !plugin_loaded) | ||
884 | { | ||
885 | int fd; | ||
886 | logf("Plugin '%s' leaks file handles", plugin); | ||
887 | |||
888 | static const char *lines[] = | ||
889 | { ID2P(LANG_PLUGIN_ERROR), | ||
890 | "#leak-file-handles" }; | ||
891 | static const struct text_message message={ lines, 2 }; | ||
892 | button_clear_queue(); /* Empty the keyboard buffer */ | ||
893 | gui_syncyesno_run(&message, NULL, NULL); | ||
894 | |||
895 | for(fd=0; fd < MAX_OPEN_FILES; fd++) | ||
896 | if(open_files & (1<<fd)) | ||
897 | close_wrapper(fd); | ||
898 | } | ||
899 | #endif | ||
900 | |||
853 | sim_plugin_close(pd); | 901 | sim_plugin_close(pd); |
854 | 902 | ||
855 | if (rc == PLUGIN_ERROR) | 903 | if (rc == PLUGIN_ERROR) |
@@ -926,3 +974,37 @@ char *plugin_get_current_filename(void) | |||
926 | { | 974 | { |
927 | return current_plugin; | 975 | return current_plugin; |
928 | } | 976 | } |
977 | |||
978 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | ||
979 | static int open_wrapper(const char* pathname, int flags) | ||
980 | { | ||
981 | int fd = PREFIX(open)(pathname,flags); | ||
982 | |||
983 | if(fd >= 0) | ||
984 | open_files |= 1<<fd; | ||
985 | |||
986 | return fd; | ||
987 | } | ||
988 | |||
989 | static int close_wrapper(int fd) | ||
990 | { | ||
991 | if((~open_files) & (1<<fd)) | ||
992 | { | ||
993 | logf("double close from plugin"); | ||
994 | } | ||
995 | if(fd >= 0) | ||
996 | open_files &= (~(1<<fd)); | ||
997 | |||
998 | return PREFIX(close)(fd); | ||
999 | } | ||
1000 | |||
1001 | static int creat_wrapper(const char *pathname) | ||
1002 | { | ||
1003 | int fd = PREFIX(creat)(pathname); | ||
1004 | |||
1005 | if(fd >= 0) | ||
1006 | open_files |= (1<<fd); | ||
1007 | |||
1008 | return fd; | ||
1009 | } | ||
1010 | #endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */ | ||