My understanding of all the parts here is weak. I want an interactive PHP web app X, to allow users to start an often lengthy server-side PHP script called Y. Because Y can take a long time to complete and produces no directly relevant output, I don't want X to block on Y completing. So my desired goal is for X to use a socket to "fork" Y off on its own connection to the server. Up until recently, code in X that I can simplify to the following was sufficient to launch and complete script Y on my server:
$fp = fsockopen ("ssl://www.myserver.com", 443);
if ($fp) {
echo "Y is starting";
fwrite($fp, "GET /path/SCRIPT-Y.php HTTP/1.1\r\n"
."HOST: www.myserver.com\r\n"
."\r\n");
fclose($fp);
}
This is the approach recommended e.g. here.
However, some recent change to my (externally hosted and largely opaque) server environment (I don't know what) has caused this logic to start to fail. Most if not every time, now, script Y fails to execute, despite "Y is starting" indicating a successful fsockopen. (Above code is a minimalist reduction of my actual code; in actual code, fsockopen() watches errNo and errStr but they are always zero/null.)
Empirically, I see two behaviors from slight changes to this code:
with the socket open, if I block and report output from the connection until feof(), script Y actually DOES complete. The loop lasts until server timeout or, if I add a "Connection: Close" header, until script completion, but both are unacceptably long for code running in X.
if I remove the fclose() call, this code returns immediately, and my server successfully runs Y.
Putting these two observations together, I hypothesize that closing the connection in X somehow kills not only the connection but the process Y associated with it on my server. I can understand that as theoretically useful in a stateless / zero-side-effect paradigm -- if there is no consumer of output, there is no need to execute the program -- but here obviously I'm interested in Y's side-effects rather than its direct output so need its process to stay alive.
I feel like adding a Close:Connection header so the server closes the connection "when Y is done" but not calling fclose() in X gives me the behavior I want. However, orphaning the open socket connection -- not calling fclose() -- feels very wrong; X runs "forever" and so would leak a socket-descriptor every time users launch Y. (If I was reasonably guaranteed the number of sockets I could orphan was in the hundreds of thousands, I could go this route though...Y is actually a Google Calendar event-posting transaction; and I know in life of app my users will post thousands but not hundreds of thousands of calendar events between server restarts :-).)
What is the transaction pattern I'm really looking for, here, and how do I implement it robustly in PHP? Do I really have to track a queue of open connections in X and poll them for Y's self-reported completion before closing each manually? I am hoping to avoid polling or launching threads; ideally I just want to "launch and forget." (It would be fine for a Y process so launched to "time out" after a while; I just don't want my user in X to have to block on that time out!)
Thanks in advance for any help.