Shell_exec starts a process, but does not return when the process ends

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)

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;

}
Sponsor our Newsletter | Privacy Policy | Terms of Service