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日 把对软链的操作更改过来了。以后全部操作只对软链本身有效。
文章详细描述了一个关于软链接在复制和剪切操作中导致的死循环问题,以及如何通过避免深入文件夹内部操作来解决这一问题。文中还指出,在前端处理软链时,应当将其视为单个文件处理,而非文件夹,以防止循环引用。通过分析gdb打印信息和代码逻辑,作者揭示了问题的根源,并提出了有效的解决方案。

被折叠的 条评论
为什么被折叠?



