A way to cancel a File's Copy Process
-
Hi, I am development a small interface to allow users to import files into my project solution.
I am worry about a cancel process. There can be loads of media files so the files might be quite long. I have found some solutions as to make a buffer and check for a flag e.g.
In Windows API there is a method called CopyFileEx that has a flag to abort the process. But my program is going to be multi-platform so I cannot use the Windows API.Is there any similar method in QFile or in another Qt Class?
If I put the process in a QThread and I kill it, what would be the result? (Because later I could remove the file) -
Hi and welcome to devnet,
If you want to have control over file copying then you should do it by hand one block after the other.
When you say "kill it", do you mean stop it gracefully or terminate it ? In the former case, you handle the stopping cleanly. In the second case, the state is unknown so you can't make any assumption about it.
-
@SGaist Thanks for answering!
If you want to have control over file copying then you should do it by hand one block after the other.
What do you mean? Doing a buffer for copying the file little by little?
When you say "kill it", do you mean stop it gracefully or terminate it ?
I meant any of the two forms. If I create a thread and I kill or stop it, what will it happen with the file? For example, if it is a video file, will it remain with the copied data so I will have to delete it? I would try to stop the thread instead of killing it, of course.
-
@ars1614 said:
What do you mean? Doing a buffer for copying the file little by little?
That is it, yes.
If I create a thread and I kill or stop it, what will it happen with the file? For example, if it is a video file, will it remain with the copied data so I will have to delete it?
This is somewhat undefined. At best the file will be closed and will contain whatever you've written into it. At worst, which is most of the time, however, the buffers won't be flushed and the file descriptor will be left open. Meaning that the file will contain the last data that was flushed to it and the ability to close it is lost. And to pile up, as windows locks the files when writing you won't be able to close it or delete the file by other means.
So, don't terminate your thread! If you want to be sure that application exits gracefully in most cases, intercept the SIGTERM/SIGINT/SIGSEGV signals and do your cleanup manually so you can ensure the file is flushed and the file descriptor is freed. Also don't call
::exit()
as it doesn't perform cleanup on local stack-based objects and/or make sure that the object is deleted if you hold it in the heap (QFile
will callclose()
in its destructor).Kind regards.
-
@ars1614 said:
Uff... Too much work only for cancelling a copy of a file.
Well, no easy solutions here, if you're after a two-liner you're out of luck. Or, you can live with the limitations
QFile::copy
has and use that instead.waiting for Qt to see if they release something about before hehe.
I really doubt something will be changed in that regard. This is very platform specific (on Linux there's only advisory locking) and what I described is a somewhat overprotected case. Usually the applications will just open the file, copy it and will leave it as it is if someone terminates them. By the way, this locking will also occur if you use
CopyFileEx
and the application is terminated forcefully, so it's by no means Qt's fault. No one is supposed to clean up your objects/handles but you.I had recently encountered something of the like when I was working on the windows implementation of my service library:
I've forgotten to close the service handle after requesting the service be deleted, so windows has marked the service for deletion (as expected) but that was deferred so after my program closed and I lost the handle there was no way to enforce the deletion to happen. Ultimately, the service was deleted when I restarted the OS, but that's not a good behavior in my opinion, so I put the effort to find and fix the problem.Kind regards.
-
I am not sure if you want to be able to cancel while copying a particular file or if you want to cancel copying a lot of files (at some point before all files have been copied).
For an individual file you can write your own copy function and hook into this anyway you want (including by adding a copy progress output or something like that). There is no reason why you cannot open both files (one for reading, the other for writing).
I would probably put this in a thread. Give it a list of files to copy, provide signals for overall status and individual status, and have an option to cancel. This sounds like a perfect reason to have a thread...
-
To add to my fellows: never kill (as in terminate) a thread unless you have no other choice. The state is undefined if you do that. In that case, as @kshegunov mentioned, it's your responsibility to clean (i.e. close and erase the file)
-
Thanks to all of you.
I have no time to dedicate close to a day to implement and test a method to copy files little by little (although there have to be loads of code parts already implemented I'm sure). By the moment, If the user is copying a large list of files and wants to interrupt the process, the process will finish when it finishes to copy the current file at that moment, and will erase the previous files. If the current file is huge, the user is going to wait until the end of the copy.
We know now the behaviour of the Qt copy process, so in the future if it is a problem for somebody, we will have to implement the buffer...
Again, thanks!