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)
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;

}

I’m not saying this is the issue, but in pathmonitor.exe shouldn’t your two arguments be argv[0] and argv[1] rather than as you have them, 1 and 2? I don’t do much C, but normally c arrays are zero-indexed. That said, I’m sure you would have noticed the incorrect information in the log file.

argv[0] contains always the program or batch name you executed. So the argv array is some kind of whole command line stored

1 Like

Of course it does. Sorry, it’s been a while.

1 Like

No one has a clue? No one gets worried? Quite serious after all if you have a system based on php

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.