Weblog Navigation
First Previous Index Next Last
Background Processes On Windows (Saturday, September 11th, 2010)

Sometimes Windows makes me want to kill myself.

It was a simple enough idea: I've got a task to be performed, which can take anywhere from several seconds to a minute or two. I want to activate it from a web page, and display a progress bar to the user. To make this work on the web, of course, this means the initial request has to spawn a background process and terminate, then I'll use AJAX to make subsequent calls to another script that checks on the progress, and update the progress bar every couple of seconds.

It's a little more complex than you might expect, if you're not familiar with web development. But on UNIX-based systems, it's really not that complicated. Unfortunately, I needed to do this on a Windows server.

It turns out that Windows doesn't have anything equivalent to fork(). PHP's pcntl_fork() doesn't exist on Windows. Perl's fork() is a crazy hack that uses threads to emulate pseudoprocesses, but the parent thread can't exit until the child threads are done. It's supposed to be possible to create a WScript.Shell COM object and call the Run method, but while this worked fine when I tried it from command line, I couldn't get it to work when running it from a web page. There were no error messages anywhere I could find, so I still don't know why that didn't work.

Eventually I downloaded the PsTools package from SysInternals, and was able to use psexec -d to successfully spawn a background process. Unfortunately the first time you run it, a dialog box pops up and requires you to accept a license agreement, which is a little awkward when you're trying to run it from within a web server. However, I was able to use the RunAs command (Windows' equivalent to sudo) to run psexec as the web server user and acknowledge the resulting dialog box that way.

There was just one other minor hurdle: even though I set $|=1 to explicitly disable output buffering in the Perl script that I eventually got running as a background process, it apparently still buffers output somewhere, because the file I was writing my progress to remained 0 bytes until the file was closed. I had intended to keep the file open for writing, appending to it as I went. I figured out a better way to report progress, so now I'm repeatedly opening the file, writing to it, and closing it again, but without keeping a running transcription of every last detail.

In the end, I got it working, and the resulting progress bar works perfectly. It was quite an adventure in frustration and annoyance, but now I know what to expect if I ever need to do something like this again.

Weblog Navigation
First Previous Index Next Last