Parent process file Handle Quilt process occupation
Scenario Description:
1. Parent process A uses the function fopen to open (create) a disk file file.exe.tmp
2. Parent process for long-time side-download side writes
3. When the download is complete, close the file handle using fclose
4. Rename File.exe.tmp to File.exe
The above is the ideal code execution process.
Problem:
In the fourth step, renaming the file may fail, using the GetLastError function to discover the cause of the failure for this file being consumed by another process.
Solve:
1. Use Microsoft's official developer Handle.exe to find out which process is taking up this file
(Handle.exe's https://technet.microsoft.com/en-us/sysinternals/bb896655.aspx)
How to use: Execute the Handle.exe file.exe.tmp/accepteula command (use the pipe to get direct results and print) before the file download is complete and the rename function is executed.
2. In the printout, it was found that the file was occupied by child process B of parent process A.
During the file.exe.tmp download process, parent process a uses the CreateProcess function to create child process B and look at the function prototype:
BOOL WINAPI CreateProcess (
_in_opt_ LPCTSTR Lpapplicationname,
_inout_opt_ LPTSTR lpCommandLine,
_in_opt_ Lpsecurity_attributes Lpprocessattributes,
_in_opt_ Lpsecurity_attributes Lpthreadattributes,
_in_ BOOL bInheritHandles,
_in_ DWORD dwCreationFlags,
_in_opt_ LPVoid Lpenvironment,
_in_opt_ LPCTSTR Lpcurrentdirectory,
_in_ Lpstartupinfo Lpstartupinfo,
_out_ lpprocess_information lpprocessinformation
);
Where the bInheritHandles parameter is described as:
If This parameter TRUE, each inheritable handle in the calling process was inherited by the new process. If The parameter is FALSE, the handles was not inherited. Note that inherited handles has the same value and access rights as the original handles.
In a nutshell, the child process is allowed to inherit the handle of the parent process.
3. A simple workaround: The bInheritHandles parameter is set to Flase, then child process B will not occupy this file.
But I can't use this method here, because this subprocess B is a third-party program, and he has to inherit some handles to play, so I'll fix it in a different way.
4. Look at the fopen function, implement the code in the CRT, the CRT code is open source, the path is: Microsoft Visual Studio 10.0\vc\crt\src
A layer down, and found that fopen is actually the __topenfile function, the __topenfile function has a detailed file open mode processing process.
There is a code in the mode processing process:
Case _t (' N '):
Modeflag |= _o_noinherit;
Break
The _o_noinherit is defined as:
/* Open handle inherit bit */
#define _O_NOINHERIT 0x0080/* Child process doesn ' t inherit file */
This is to control whether the handle allows the quilt process to occupy.
Then you just need to set the mode of fopen to "Ab+n".
Along the source continues to look down, found in the CRT layer the final call function is _tsopen_nolock (file \microsoft Visual Studio 10.0\vc\crt\src\open.c)
There is a lot of processing for flag, and finally called the CreateFile function to create, open the file, and there are a lot of CreateFile function exception handling code.
CreateFile function is the system API, not open source, to continue to follow the reverse, it will not continue down.
5. So the 3rd solution: Create, open files directly using the System API CreateFile,
6. Fourth solution: Refer to Unlock method: First OpenProcess, then copy the handle through DuplicateHandle, and then end the handle to resolve the child process B's occupation. This method online can easily search the source code, I will not nonsense.
7. Summary
There are 4 ways to solve the problem of the parent process handle quilt process, the following comparison of 4 scenarios:
1.CreateProcess setting Parameters: very convenient, but not applicable if the child process has special inheritance handle requirements
2.fopen setup parameters: Very convenient, cross-platform compatible, modify the code only need to add a byte to solve the problem
3. Use CreateFile to create, open files, replace fopen:createfile powerful, but to play in business software This function is not easy, need to handle a large number of exceptions (can refer to the implementation of _tsopen_nolock function source code)
4.DuplicateHandle after CloseHandle: The most powerful way to close handles in other processes, mainly used in the Ring3 to remove the simple Trojan Virus file occupancy technology (can not be applied to the file of the pit technology), but the use of risk is there, Real applications also need to write a lot of exception handling code.
Parent process file Handle Quilt process occupation