bug见tower:
重现方式:(注此bug已于20130716日修复)
首先在文件管理器中创建一个文件夹的软链(文件夹中要有文件),然后下面是两种不同方法,都会挂掉
1. 在软链上右键复制--->到桌面上粘贴
2. 在软链上剪切---->在桌面粘贴这个软链--->然后在桌面再次复制粘贴软链。
会弹出是否覆盖的提示,这个随意选择,最后会报错误: “当复制文件时出错”
最后点击确定,桌面必挂。
gdb 打印信息:
Program received signal SIGSEGV, Segmentation fault. 0x0000000000422dd4 in _copy_files_async (src=0xc1b340, data=0xc0b770) at /home/ycl/dde/lib/dentry/fileops.c:675 675 if (response->apply_to_all) (gdb) bt #0 0x0000000000422dd4 in _copy_files_async (src=0xc1b340, data=0xc0b770) at /home/ycl/dde/lib/dentry/fileops.c:675 #1 0x0000000000422f53 in _copy_files_async (src=0xc1b340, data=0xc0b770) at /home/ycl/dde/lib/dentry/fileops.c:719 #2 0x0000000000421bcd in traverse_directory (src=0xc1b340, pre_hook=0x422b43 <_copy_files_async>, post_hook=0x42253f <_dummy_func>, data=0xc0b770) at /home/ycl/dde/lib/dentry/fileops.c:88 #3 0x0000000000421dc8 in traverse_directory (src=0x730c80, pre_hook=0x422b43 <_copy_files_async>, post_hook=0x42253f <_dummy_func>, data=0xb6bd80) at /home/ycl/dde/lib/dentry/fileops.c:154 #4 0x0000000000421dc8 in traverse_directory (src=0x730b20, pre_hook=0x422b43 <_copy_files_async>, post_hook=0x42253f <_dummy_func>, data=0xb65c10) at /home/ycl/dde/lib/dentry/fileops.c:154 #5 0x00000000004224c2 in fileops_copy (file_list=0x9bff60, num=1, dest_dir=0x6e66a0) at /home/ycl/dde/lib/dentry/fileops.c:375 #6 0x0000000000426178 in fileops_paste (dest_dir=0x6e66a0) at /home/ycl/dde/lib/dentry/fileops_clipboard.c:134 #7 0x00000000004219be in dentry_clipboard_paste (dest_dir=0x6e66a0) at /home/ycl/dde/lib/dentry/entry.c:894 #8 0x0000000000417c61 in __clipboard_paste__ (context=0x7fff92fe20d0, function=0x7fff9046d920, thisObject=0x7fff9046eaa0, argumentCount=1, arguments=0x7fffffffcd28, exception=0x7fffffffcce8) at /home/ycl/dde/build/app/desktop/_gen_dentry.c:1363
1.先记录一下:
dentry_copy:只复制symlink本身,不复制软链对应的文件或者文件夹
dentry_copy_dereference_symlink:还会进入symlink遍历。但是这样很容易由树成图,进入死循环。
现在的问题在于前端现在没有对软链进行单独处理,而是当做一般文件处理,然后进入traverse_directory中遍历(但是核心问题在于traverse_directory中把软链当成文件夹进行复制的,本来设置的是G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) 并使用_copy_files_async进行复制。
此处还需进一步查找问题。
2.虽然有单独的软链复制函数
JS_EXPORT_API
void dentry_copy_dereference_symlink(ArrayContainer fs, GFile* dest_dir)
但是这个函数是把软链当单个文件处理的,此处显然有问题!
static void _do_dereference_symlink_copy(GFile* src, GFile* dest) { GError* error = NULL; if (!g_file_copy(src, dest, G_FILE_COPY_NONE, 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);
没有分开处理单个文件的软链和文件夹的软链这两种不同的情况。
3.乾哥找出如下bug
a.shift+delete 删软链时,文件夹内部文件被删除,但是软链对应的文件夹本身没有被删除
b. 直接delete时,文件夹内部文件每被删除,仅仅删除了软链
4.
进一步查找1中的疑问发现,虽然设置了 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,但是没有先检测是否是symbolic_link,如果是,应直接goto post_processing
gboolean traverse_directory (GFile* src, GFileProcessingFunc pre_hook, GFileProcessingFunc post_hook, gpointer data) { 。。。。。。。。。。。。。。 //here, we must be in a directory. //check if it's a symbolic link if (pre_hook (src, data) == FALSE) //src_enumerator must be freed { retval = FALSE; goto post_processing; } #if 1 char* src_uri = NULL; src_uri = g_file_get_uri (src); g_debug ("traverse_directory: chdir to : %s", src_uri); #endif //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; } GFileInfo* file_info = NULL; while ((file_info = g_file_enumerator_next_file (src_enumerator, NULL, &error)) != NULL) { 。。。。。。。。。。。。。。。。。。。。。。。
总结:
其实对于软链,如果当做文件夹那样复制或者删除等操作,后果很有可能会进入死循环(软链中还有软链,这种情况不是没可能出现)。
故最好的解决方案,应该如同nautilus中那样,不论单个文件软链,还是文件夹软链,仅仅只是当做单个文件进行复制剪切粘贴,而不遍历进文件夹内部操作。
所有操作只对软链本身而言,而不对内部文件产生任何影响。
注:code中已经于20130716日 把对软链的操作更改过来了。以后全部操作只对软链本身有效。