php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #59164 Inconsistent parent process id used when no APP_POOL_ID.
Submitted: 2010-04-15 10:34 UTC Modified: 2010-04-27 13:56 UTC
From: RQuadling at GMail dot com Assigned:
Status: Wont fix Package: WinCache (PECL)
PHP Version: 5.3.2 OS: Windows XP SP3
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2010-04-15 10:34 UTC] RQuadling at GMail dot com
Description:
------------
Currently, to allow multiple CLI based scripts to share 
wincache_ucache, the environment 
variable APP_POOL_ID must exist prior to the first script 
being loaded.

This may not always be possible, especially when the script 
is not being run from the command 
line.

If the environment variable doesn't exist, then wincache 
uses the parent process's process id to 
identify the cache. This could be the process id of cmd.exe 
when launched manually, or 
srvany.exe (part of MS Resource Tool Kit) if running as a 
service or php.exe if script a 
launches script b.

I'm using COM WShell->Run() to create non blocking child 
processes.

Under these conditions, the child processes correctly 
identify the parent process (all the 
children see the same parent), but the parent process is 
looking at its parent, the cmd.exe or 
srvany.exe

As such, there are different results to getppid() when using 
APP_POOL_ID is not set

With that, the parent script cannot access the 
wincache_ucache of the child scripts.



I would suggest the following logic when APP_POOL_ID does 
not exist.

1 - Find this process's id in the process snapshot.
2 - Find the top most process id for the same process name 
(pe.szExeFile I think is the place to 
look).


If it was possible to set the identifier at run-time, then 
the value could be passed to the 
child scripts, just like the session id gets passed in 
cookies, etc.



Reproduce code:
---------------
<?php
function showCache() {
  echo 'Last updated by instance #', wincache_ucache_get('i_Instance'), ' at ', date('r', wincache_ucache_get('f_Current')), "\r";
}

if (!isset($argv[1])) {
  wincache_ucache_add('i_Instance', 0);
  wincache_ucache_add('f_Current', $Start = microtime(True));
  $WshShell = new COM("WScript.Shell");
  foreach(range(1, 3) as $Task) {
    echo "Starting Task:$Task" . PHP_EOL;
    $oExec = $WshShell->Run(__FILE__ . " $Task", 9, false);
  }
  while(microtime(True) < ($f_Start + 100)){
    showCache();
  }
} else {
  foreach(range(1, 100) as $Step) {
    wincache_ucache_set('i_Instance', $argv[1]);
    wincache_ucache_set('f_Current', microtime(true));
    showCache();
    time_sleep_until(microtime(True) + rand(1, 500) / 100);
  }
}


Expected result:
----------------
The main window will show a changing value for the updates to 
the cache.

Actual result:
--------------
No changes.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-04-23 13:50 UTC] don dot raman at microsoft dot com
Can you let me know why setting of environment variable APP_POOL_ID is not a feasible solution? You can always set this at a global level and not through script. Where from you are trying to run the script? There should be a way to set environment variable from anywhere and not necessary command line.

Thanks,
Don.
 [2010-04-24 06:01 UTC] RQuadling at GMail dot com
I currently have a series of processes (BAT and PHP scripts) 
which process faxes. Around 1000 faxe a day and 24/7.

The process currently run as desktop programs on a logged in 
machine. Not ideal, but worked for the while.

The sysops/admins have asked for a way in which these can be 
start/stopped automatically.

My solution is to use PHP with win32service/wincache to 
provide a windows service. I've got most of this mapped out.

I'll have several layers to the code:

1 Service (Fax, Ultrasonics, Shearography, etc.) launches 
Service Pools (Collector, Queues, ProcessA, ProcessB, etc.) 
launches Service Threads (Task specific short term actions).

So, having a way to pass information up and down the chain 
of tasks would be ideal.

The only way I can get this working is to create a system 
wide APP_POOL_ID. The server doesn't have IIS, so the mis-
use is probably fine, but it does mean that where I have 
many services, each using common base classes, I end up with 
1 BIG cache, rather than 1 cache per service.

I've made some minor local changes to the win32service 
extension (no karma) to allow more interaction with the 
windows service manager.

This last small hurdle would allow me to have PHP based code 
running and responding to windows services startup/shutdown, 
without logging in.

Windows service manager would tell my php based service 
scripts to stop, this could be passed to the service pool to 
stop making new threads, shutdown the gatherers, flush the 
queues, etc. and for the threads, suspend activity and 
shutdown. If the thread can rollback, then do so. Basically 
clean up and die.

But having 1 APP_POOL_ID for the server is the issue.

There is code in wincache dealing with no APP_POOL_ID, but 
it doesn't work for me as wincache always looks at the 
parent of the current script, so if script A launches script 
B, they are not looking at the same process and therefore 
cannot share wincache.
 [2010-04-26 16:57 UTC] don dot raman at microsoft dot com
So if my understanding is correct we have N number of service/process and each one wants its own APP_POOL_ID. Why not set a unique APP_POOL_ID in all these services. This way you will have N number of wincache user cache shared memory. One of the way to do this in a easy way can be to write N number of batch file which starts/stops the service and prior to that sets the environment variable to a unique APP_POOL_ID. This way all the process or sub-process forked from this command window will inherit this environment variable and will use it's own unique shared memory.
 [2010-04-27 06:32 UTC] RQuadling at GMail dot com
Setting APP_POOL_ID and then calling NET START will not pass 
the APP_POOL_ID to the 
service started with NET START.

But, due to the joys of SysInternals RegMon and a quick 
Google, it seems that each 
service can have a REG_MULTI_SZ called Environment.

So I can set APP_POOL_ID per service.

Excellent.

Now just got to amend win32service so that this can be done 
using win3_create_service.

I've got code to set the description which was easy 
enough...
 [2010-04-27 13:56 UTC] don dot raman at microsoft dot com
Thank you for taking the time to write to us, but this is not
a bug.

Richard, I am closing this bug as you have a decent work around. Please feel free to re-open it if this is not the case.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Wed Jul 17 11:01:25 2019 UTC