Hello. Hope everything is fine.
There is a problem in my program that I have not been able to troubleshoot. I can not use that code here because it gets too complicated, so I have used a simplified example that reproduces the problem.
I have three files test1.php, test2.php and test3.php. They all do the same thing, they start a process called pathmonitor.exe. Pathmonitor.exe monitors a folder and returns when a file in the folder has been edited.
There is a slight difference between test1.php, test2.php and test3.php. They each want to monitor their own folder. test1 specifies c:/folder1 as the folder to monitor, test2 specifies c:/folder2 and test3 specifies c:/folder3.
Insert.php is used to write in the folders. You can either choose to write in c:/folder1 and c:/folder2, or in c:/folder1 and c:/folder3. In other words, two folders at the same time.
So when you press one of the options, pathmonitor.exe should return from the folder it is monitoring, which means that shell_exec (which started pathmonitor.exe) also returns.
Here’s the problem. Shell_exec does not always return. It gets stuck and waits for pathmonitor.exe, but pathmonitor has already returned. I know this is true because pathmonitor.exe logs when it exits.
So it’s strange why shell_exec gets stuck. Maybe a bug?
The problem is demonstrated in this video. (You will need to pause the video when text message appears, otherwise you will not have time to read)
https://www.youtube.com/watch?v=NCV0_ibyoGs
test1.php, test2.php and test3.php looks like below. The only difference is the "$folder variable".
//monitor path
$folder = "c:/folder1"; //test1.php
$folder = "c:/folder2"; //test2.php
$folder = "c:/folder3"; //test3.php
while(1) {
$id = uniqid();
echo "start - $id<br>";
flush();
//start pathmonitor.exe and tell it to monitor $folder. $id is used for logging
shell_exec("pathmonitor.exe $folder $id");
echo "end - $id<br><br>";
flush();
}
insert.php looks like this
<a href="?path1=c:/folder1/file.txt&path2=c:/folder2/file.txt">folder1 & folder2</a>
<a href="?path1=c:/folder1/file.txt&path2=c:/folder3/file.txt">folder1 & folder3</a>
<?php
if(!empty($_GET['path1']) && !empty($_GET['path2']))
{
file_put_contents($_GET['path1'], "notify", LOCK_EX);
file_put_contents($_GET['path2'], "notify", LOCK_EX);
}
?>
pathmonitor.exe
#include "Windows.h"
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
// Create and open a text file
ofstream MyFile("C:/xampp/htdocs/monitor-main/cpp.txt", ios::app);
//Setup monitor
HANDLE h = CreateFileA(argv[1], (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_WRITE | FILE_SHARE_READ), 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
unsigned long bytes = 0;
FILE_NOTIFY_INFORMATION f[2000];
//Log start
MyFile << "start - " << argv[1] << " - " << argv[2] << "\n";
MyFile.flush();
//Start monitor (waiting/blocking)
ReadDirectoryChangesW(h, &f, 2000, false, FILE_NOTIFY_CHANGE_LAST_WRITE, &bytes, NULL, NULL);
// Log end
MyFile << "stop - " << argv[1] << " - " << argv[2] << "\n";
MyFile.flush();
return 1;
}