DDE后端之dentry(一):从测试经验看运行机制
http://kms.linuxdeepin.com/?p=2214
上面一篇文章和这篇应该一起看,建议先看第一篇文章。
dentry源码:https://github.com/linuxdeepin/dde/tree/develop/lib/dentry
测试代码源码:https://github.com/linuxdeepin/dde/tree/desktop_test/app/desktop/test
直入正题:
1.nautilus网络文件的拖动问题,或者整个文件夹的复制。不能复制文件夹内部文件的原因:api不支持对网络文件夹内部文件遍历。---未解决
if (g_file_is_native (src)) traverse_directory (src, _copy_files_async, _dummy_func, data); else _copy_files_async (src,data);
代码位置:dde/lib/dentry/fileops_copy.c -->fileops_copy()
此处判断如果是网络文件,那么traverse_directory
若是本地文件,直接_copy_files_async
此处需改进
这个等下半年做文件管理器时修
2.桌面必挂Bug---已解决
bug见tower:
重现方式:(注此bug已于20130716日修复)
首先在文件管理器中创建一个文件夹的软链(文件夹中要有文件),然后下面是两种不同方法,都会挂掉
1. 在软链上右键复制—>到桌面上粘贴
2. 在软链上剪切—->在桌面粘贴这个软链—>然后在桌面再次复制粘贴软链。
会弹出是否覆盖的提示,这个随意选择,最后会报错误: “当复制文件时出错”
最后点击确定,桌面必挂。
详情见:
http://kms.linuxdeepin.com/?p=2255
//begin g_file_enumerator_next_file ,we must check if the file type is symbolic_link then goto post_processing: GFileType type = g_file_query_file_type (src, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL); if (type == G_FILE_TYPE_SYMBOLIC_LINK) { //TODO: symbolic links g_debug ("-------src type is symbolic_link-------"); goto post_processing; }
3. 对于symlink也有待改进---------已解决,且标准化
dentry_copy:只复制symlink本身,不复制软链对应的文件或者文件夹
dentry_copy_dereference_symlink:还会进入symlink遍历。但是这样很容易由树成图,进入死循环。
static void _do_dereference_symlink_copy(GFile* src, GFile* dest, GFileCopyFlags copy_flag) { GError* error = NULL; if (!g_file_copy(src, dest, copy_flag, NULL, NULL, NULL, &error)) { g_warning("error message: %s, error code: %d\n", error->message, error->code); FileOpsResponse* response; response = fileops_move_copy_error_show_dialog(_("copy"), error, src, dest, NULL); if (response != NULL) { switch (response->response_id) { case GTK_RESPONSE_CANCEL: //cancel all operations g_debug ("response : Cancel"); break; case CONFLICT_RESPONSE_SKIP: //skip, imediately return. g_debug ("response : Skip"); break; case CONFLICT_RESPONSE_RENAME: //rename, redo operations g_warning ("response : Rename to %s", response->file_name); GFile* dest_parent = g_file_get_parent(dest); GFile* new_dest = g_file_get_child (dest_parent, response->file_name); g_object_unref(dest_parent); _do_dereference_symlink_copy(src, new_dest, copy_flag); g_object_unref(new_dest); break; case CONFLICT_RESPONSE_REPLACE: { g_file_copy(src, dest, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL); g_debug ("response : Replace"); break; } default: break; } fileops_response_free (response); g_error_free(error); } } }
4.不够完善,需要改进的traverse_directory中的g_warning------已解决
fileops_moving时
** Message: fileops_move: Begin moving files ** Message: fileops_move: file 0: file:///home/ycl/dde/build/test_files/skype.desktop to dest: file:///home/ycl ** Message: GFileType=2 ** (desktop:25391): WARNING **: traverse_directory 1: 没有那个文件或目录 ** Message: fileops_move: End moving files
说明:
文件是存在的,但是还是报了警告
source:
g_warning ("traverse_directory 1: %s", error->message);
g_warning ("traverse_directory 2: %s", error->message);
g_warning ("traverse_directory 3: %s", error->message);
location:
traverse_directory()内
5. 测试时挂掉的地方:------已解决
** (desktop:24641): DEBUG: _delete_files_async: delete : file:///home/ycl/test_files/brasero.desktop ** (desktop:24641): DEBUG: traverse_directory: come out: file:///home/ycl/test_files ** (desktop:24641): DEBUG: _delete_files_async: delete : file:///home/ycl/test_files ** (desktop:24641): DEBUG: fileops_delete: End deleting files ** Message: 3delete end [ 20%] Testing dentry_move... ** (desktop:24641): ERROR **: Test dentry_move Failed Program received signal SIGTRAP, Trace/breakpoint trap. 0x00007ffff4644205 in g_logv () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 (gdb) bt #0 0x00007ffff4644205 in g_logv () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #1 0x00007ffff46443d2 in g_log () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #2 0x000000000042f438 in T () #3 0x000000000042f295 in test_entry () #4 0x000000000042e83f in desktop_test () #5 0x0000000000418996 in desktop_test_wrap () #6 0x00007ffff463da5b in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #7 0x00007ffff463ce45 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #8 0x00007ffff463d188 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #9 0x00007ffff463d5fa in g_main_loop_run () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #10 0x00007ffff5ff90a5 in gtk_main () from /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 #11 0x0000000000412446 in main () (gdb) q A debugging session is active. Inferior 1 [process 24641] will be killed. Quit anyway? (y or n) y ycl@ycl:~/dde/build$ desktop
注:
1. 自动挂掉后,gvfsd-trash 仍然占据高达2.2G的内存(那么挂掉很有可能是dentry_trash()有问题)
desktop内存高达106.5MB (我已经设置最大为int TEST_MAX_MEMORY = RES_IN_MB(90);)
(此处是因为Test.c中关于内存计算和系统计算不同,内存每溢出。)
2. 重启desktop后,内存由35M 慢慢涨到197.1M,且一直稳定在197.1M
解答:
挂在fileops_trash这了(将dentry_trash 中的fileops_trash 换成fileops_delete则一切正常)。
进入fileops_trash发现:
_trash_files_async (src, data);
//traverse_directory (dir, _dummy_func, _trash_files_async, NULL);
继续一步步深入,还是挂,最后不得不这样:
Test({ system("touch /tmp/test.c"); g_message("1trash start"); GFile* _src1 = g_file_new_for_uri("file:///tmp/test.c"); // ArrayContainer _fs1; // _fs1.data=&_src1; // _fs1.num = 1; // dentry_trash(_fs1); // ArrayContainer_free0(_fs1); g_file_trash (_src1, NULL, NULL); g_object_unref(_src1); g_message(" trash end"); },"dentry_trash");
然后结果:
[ 28%] Testing dentry_trash...** Message: 1trash start ** Message: trash end [ 28%] Testing dentry_trash... ** (desktop:20703): ERROR **: Test dentry_trash Failed
跟踪/断点陷阱
仍然挂。。。。。
至此,找出了glib 中g_file_trash 的一个bug了。
gboolean g_file_trash (GFile *file
,GCancellable *cancellable
,GError **error
);
trash 次数 2800次以上,必挂! 而且是引起整个DDE桌面挂掉。
可能原因: trash时不仅仅只是将文件move到回收站,而且gvfsd-trash还记录了trash的GFile的info信息。
如下:
ycl@ycl:/tmp$ cd ~/.local/share/Trash/ ycl@ycl:~/.local/share/Trash$ l expunged/ files/ info/ ycl@ycl:~/.local/share/Trash$ cd info/ ycl@ycl:~/.local/share/Trash/info$ l skype.1000.desktop.trashinfo test.11071.c.trashinfo test.13131.c.trashinfo test.1766.c.trashinfo test.3827.c.trashinfo test.5888.c.trashinfo test.7948.c.trashinfo skype.1001.desktop.trashinfo test.11072.c.trashinfo tes
很可能是trash次数过多,后台单独记录的进程跟不上trash的速度,导致挂掉的
case G_IO_ERROR_NOT_FOUND: //TODO: showup a message box and quit. g_debug("G_IO_ERROR_NOT_FOUND");
这个等有时间再慢慢修。
// test_thumbnails();//test over
//
// but there is a bug ,but cannot be reviewed ,and it is hard to be shown :
// after test programe run 100% over,there perhaps be a error to kill ./desktop -d but without any messageout
// when I run test in gdb ,still no useful messageout
// when I run test in valgrind to track the memory-out,it messageout:
// ==9299== by 0x7A95AC0: _cairo_compositor_paint (cairo-compositor.c:65)
// ==9299== by 0x7AD9640: _cairo_surface_paint (cairo-surface.c:2022)
// ==9299== by 0x7A9D18B: _cairo_gstate_paint (cairo-gstate.c:1067)
// ==9299== by 0x7A97DC8: _cairo_default_context_paint_with_alpha (cairo-default-context.c:969)
// ==9299== by 0x7A90726: cairo_paint_with_alpha (cairo.c:2026)
// ==9299==
// ==9299== LEAK SUMMARY:
// ==9299== definitely lost: 6,288 bytes in 11 blocks
// ==9299== indirectly lost: 16,790 bytes in 674 blocks
// ==9299== possibly lost: 1,821,394 bytes in 16,770 blocks
// ==9299== still reachable: 2,152,849 bytes in 18,993 blocks
// ==9299== suppressed: 0 bytes in 0 blocks
// ==9299== Reachable blocks (those to which a pointer was found) are not shown.
// ==9299== To see them, rerun with: --leak-check=full --show-reachable=yes
// ==9299==
// ==9299== For counts of detected and suppressed errors, rerun with: -v
// ==9299== ERROR SUMMARY: 1655 errors from 1655 contexts (suppressed: 3 from 3)
// 已杀死
//there still isnot any useful DEBUG message
//and I g_message in somewhere (begin function ,end function ,begin if and so on ),but ,there still isnot DEBUG message useful
9.
/* make
/home/ycl/dde/lib/dentry/fileops_trash.c: 在函数‘fileops_empty_trash’中:
/home/ycl/dde/lib/dentry/fileops_trash.c:108:5: 警告: 不建议使用‘g_io_scheduler_push_job’(声明于 /usr/include/glib-2.0/gio/gioscheduler.h:36):Use '"GThreadPool or g_task_run_in_thread"' instead [-Wdeprecated-declarations]
/home/ycl/dde/lib/dentry/fileops_trash.c: 在函数‘_empty_trash_job’中:
/home/ycl/dde/lib/dentry/fileops_trash.c:163:5: 警告: 不建议使用‘g_io_scheduler_job_send_to_mainloop_async’(声明于 /usr/include/glib-2.0/gio/gioscheduler.h:49):Use 'g_main_context_invoke' instead [-Wdeprecated-declarations]
[ 22%] Building C object lib/dentry/CMakeFiles/dentry.dir/gnome-desktop-thumbnail.c.o
/home/ycl/dde/lib/dentry/gnome-desktop-thumbnail.c: 在函数‘gnome_desktop_thumbnail_factory_finalize’中:
/home/ycl/dde/lib/dentry/gnome-desktop-thumbnail.c:456:7: 警告: 不建议使用‘g_mutex_free’(声明于 /usr/include/glib-2.0/glib/deprecated/gthread.h:274) [-Wdeprecated-declarations]
/home/ycl/dde/lib/dentry/gnome-desktop-thumbnail.c: 在函数‘gnome_desktop_thumbnail_factory_init’中:
/home/ycl/dde/lib/dentry/gnome-desktop-thumbnail.c:752:3: 警告: 不建议使用‘g_mutex_new’(声明于 /usr/include/glib-2.0/glib/deprecated/gthread.h:272) [-Wdeprecated-declarations]
[ 23%] Building C object lib/dentry/CMakeFiles/dentry.dir/mime_actions.c.o
*/