[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] Potential MacPerl column?



Gentlemen:

   Brian: thank you for volunteering to coordinate the MacPerl column!

   Please find appended a first draft of an idea I had.  I originally 
sent this to Vicki, unfortunately the day before she had to resign. 
I have yet to spend much time on it, so if y'all just don't like it, 
that's fine.  If you do like it, I certainly expect to spend some 
more time on it; I have no idea if the length is anywhere near 
correct, for example.

   If you do like it, someone who has a clue as to the inner workings 
of the MacPerl CGI glue probably should vet it for fatal errors.

   Let me know what you think.

-David-

There are three reasons you might want to run MacPerl cgi scripts on
your Mac:

1) You would like to use it to test cgi scripts before uploading them to
a production server.

2) You want to take advantage of all the work that has been done
developing web clients to add an easy user interface to your MacPerl
program on a private network or even a single Mac.

3) You want to run a public web server on your Mac.

In my experience, MacPerl works excellently for prototyping, works well
on a small, local network, and with care can manage a lightly loaded
public server. In this column I will outline my experience, pointing out
hints and pitfalls I have discovered along the way.

Differences between MacPerl and Unix Perl:
-----------------------------------------

In my experience, the two most vexing differences between MacPerl and 
Perl running under Unix both have to do with differences between the 
Macintosh operating system and Unix:

1) Interprocess Communication models (AppleEvents on the Mac vs Pipes 
and Environmental Variables on Unix) are utterly different.  In 
general, interprocess communication is more difficult to use and much 
less generally available on a Mac.  Thus, any Unix perl program which 
makes use of interprocess communication is going to be more difficult 
to port to MacPerl.  In my opinion, use of pipes is a bad idea for 
CGI's anyway, so this is not a major problem.

The one place the differences between Unix and MacOS IPC might have 
been a problem is communication between the HTTP server and the CGI. 
This is not a problem for two reasons:
1) Chuck Shotton, when he wrote MacHTTP (the predecessor to WebSTAR), 
defined a standard for how HTTP servers should communicate with CGIs 
on the Mac, and as best I can tell, all Macintosh HTTP servers adhere 
to that standard.
2) MacPerl has an extension which allows it to communicate via this 
protocol in a way which is entirely transparent.  As a result, no 
changes should be required to move a CGI from Unix to MacPerl to Unix.

2) Unlike Unix, the Macintosh OS can only run one copy of any given 
program.  Thus, under Unix, you can have 5 copies of the same CGI or 
5 different CGIs running at the same time.  Under MacOS, you can only 
have one MacPerl CGI running at a time.  In addition, and for reasons 
I don't fully understand, this also makes it more problematic to 
implement "server push" using MacPerl.

Mechanics of Running MacPerl CGIs:
---------------------------------

The MacPerl interpreter comes in two forms; one which can be run with 
MPW and/or toolserver and a stand-alone application.  I will only 
discuss the latter form.  When you save a Perl script from the 
application, you have a couple of options as to how to save it:

1) Plain text.  The script is included as Macintosh text in the data 
fork of the file.

2) Runtime version.  The script is included as a resource in an 
application which includes a complete copy of the MacPerl 
interpreter.  The resulting file is quite large.

3) CGI.  The script is included as a resource in an application which 
accepts AppleEvents from a Macintosh HTTP server and passes them 
along with the script to the MacPerl interpreter.  The resulting file 
is small (though a bit larger than plain text.)

4) Droplet.  The script is included as a resource in an application 
which accepts drag and drop events and which passes them along with 
the script to the MacPerl interpreter.

For running a CGI on your Mac, you want to save it as CGI.

For transferring a CGI to a Unix server, you want to save it as Plain 
Text (and then transmit it as text so that the Mac newlines get 
converted to Unix newlines).

The script itself is identical to a Unix CGI.  The ever popular 
CGI.pm module is just as useful on the Mac as it is on Unix.  Thus, I 
won't explain how to write a Perl CGI here, you can read about that 
in hundreds of places.

To run this script as a CGI, you need a Web server (MacHTTP/WebSTAR, 
Quid Pro Quo, and the web sharing option in the more recent versions 
of the MacOS all work fine, as probably will any other Mac HTTP 
server.)  Put the MacPerl CGI where your HTTP server expects cgi's, 
name it as your HTTP server expects it to be named, and it should 
work.  Naming turns out to be fairly critical in many cases.  The 
safest bet in every case of which I am aware is to put ".cgi" 
(without the quotes) at the end of the filename.  There is no such 
thing as a filename extension on the Mac, and it is unusual on a Mac 
for the filename to determine function, but HTTP servers are an 
exception.  The other name you might use in some circumstances is one 
ending in ".acgi".  The ".cgi" extension signals to at least some 
webservers that the file is a cgi to be executed, but that it can 
accept only one request at a time, so that multiple requests need to 
be queued.  The ".acgi" extension signals to these same HTTP servers 
that the file is a cgi to be executed, but that it allows threading; 
that it can accept a new request while a previous request is still 
running.  MacPerl is based on Perl 5.004 and does not allow 
threading, so one would think (correctly, in most cases) that ".cgi" 
would be the correct extension for a MacPerl CGI, but as we will 
discuss later, the ".acgi" extension is unfortunately also the signal 
that server push should be used, so there are some circumstances 
where you will want to name your MacPerl CGI with the ".acgi" 
extension.

When a web browser requests your CGI, it will begin running, service 
the request, and remain running for 5 minutes.  This allows the CGI 
to service multiple requests more quickly as it doesn't have to 
restart each time.  The one disadvantage to this behavior is that if 
you are developing a script, you have to stop the CGI before you can 
restart a new version.  If you are running everything locally on one 
Mac, this is not a serious inconvenience; just select the CGI from 
the application menu in the right end of the Macintosh menu bar and 
click on the "Quit Now" button.  If you are developing on one Mac and 
running on a physically distant Mac, this can be frustrating, as you 
have no choice but to wait for the first instance of the CGI to time 
out before replacing it with a new one.  Using resedit, it is 
possible to reduce this interval to as short as 1 minute (or to 
increase it), but you will always have to wait at least one minute. 
The procedure for doing this is detailed in MPPE.

In addition to launching the CGI, you will also launch MacPerl. 
Under default conditions (e.g. if you run an unmodified Unix CGI), 
MacPerl will continue running until you stop it manually.  By adding 
the following line to your script:

####

....you can instruct MacPerl to quit when the CGI has completed. 
Complete instructions for accomplishing this are in MPPE.

Testing CGI's that will Eventually Run under Unix:
-------------------------------------------------

If the CGI uses server push, name it with a ".acgi" extension. 
Otherwise, name it with a ".cgi" extension.  If you use the ".acgi" 
extension, be sure never to make a second request to the CGI before 
the first has completed; doing so can crash the server.

Other than that, save the script as a CGI while testing it on the 
Mac, then save it as Plain Text for transfer to Unix.  If it works on 
a Mac, it will work on Unix, and in most cases, vice versa.  The only 
things to watch out for are:
* MacPerl is Perl 5.004.  5.005 and later features won't work.
* Make sure that any modules or other code you "use" or "require" is 
available on both the Unix server and the Mac.  Remember that modules 
which have binary extensions may be difficult (or even impossible) to 
port.
* Remember to set your ownership and permissions correctly on the Unix server.

Using a CGI to Provide a User Interface for a MacPerl Program:
-------------------------------------------------------------

Everyone knows how to surf the Web.  Thus, if you are developing a 
MacPerl program that is going to be used by a number of people in 
your organization,
using the Web to provide a user interface has a number of advantages:
1) You probably already know how to create web pages and forms.  In 
any case, developing for the web is easy.  Thus, you can get a user 
interface up very quickly.
2) If you have an intranet, this gives you a client/server 
architecture almost for free.
3) Because everyone knows how to surf the web, and everyone has a web 
browser on their computer, little or no training or software 
installation will be required.

There are a couple of disadvantages:
1) The Web is stateless.  Thus, saving state requires more work on 
your part.  But if you have programmed for the web, you already know 
that.
2) MacPerl CGIs can be a little unstable.  This is described in more 
detail in the next section.  Usually, however, this use of MacPerl 
CGIs involve relatively light loads and thus this is not a problem.

Using a MacPerl CGI on a Public, Macintosh Web Server:
-----------------------------------------------------

The MacOS is not a server OS; the fact that it works as one at all is 
what is surprising, not that it doesn't work perfectly.  I am 
currently running a Web server on a Mac, and as of this typing it has 
been up for 170 hours.  (This is about as long as I go without a 
reboot.)  This is a fairly complex database-backed site which in 
addition to a Web server (Quid Pro Quo), is running a mail server 
(Apple Internet Mail Server) and a name server (MacDNS), and so is 
running 9 applications all the time; I think this speaks well for the 
Macintosh as a server.  (As it happens, MacPerl is not a major part 
of this site for reasons that have nothing to do with MacPerl and 
everything to do with what the site does.)  There are a number of 
things one can do to improve the stability of the Mac as a server; 
plenty of RAM, allocating plenty of RAM to all applications, dedicate 
a Mac as a server rather than try to use one Mac both as a 
workstation and a server, remove as many extensions as possible, run 
the shareware utilities "Keep It Up" and "Autoboot" among them) but 
having done as much of that as you can, there are some MacPerl 
specific issues as well:

1) Server push is a very useful feature of the Web which allows for 
simple animations as well as returning data a little at a time when a 
CGI returns a large amount of data and/or returns it slowly.  The 
latter is important as it keeps the browser or user from timing out. 
Unfortunately, I have to recommend that you forgo that feature with 
MacPerl CGIs.  To "turn on" server push in a MacPerl CGI, you change 
the extension of the name from ".cgi" to ".acgi".  (I don't know why 
this is, or if this is a feature of MacPerl or Macintosh-based HTTP 
servers.)  Unfortunately, this also signals to the HTTP server that 
your CGI is "asynchronous", that it is threaded and can handle 
multiple hits at one time.  This is not true for MacPerl, and when a 
MacPerl ".acgi" receives a second hit while the first is executing, 
bad things happen, ranging from dropped hits to crashing the server. 
For testing a CGI prior to moving it to a Unix server, ".acgi" is 
very useful as the tester can just be careful to observe its limits. 
It might even have a place when you are using HTML to provide a front 
end to a MacPerl program if you can be pretty sure that you will 
never have overlapping hits and/or where user sophistication and 
access to the server mean that the occasional crash can be tolerated. 
I cannot imagine circumstances where this would be acceptable on a 
public server, however.

2) MacPerl CGIs have fairly high overhead, at least at startup. 
Further, only one CGI can run at a time.  If you use the ".cgi" 
extension to the CGI name, overlapping hits will be queued and 
executed in order.  This is acceptable when you have fairly few hits. 
If you are trying to develop and amazon.com or a slashdot, however, I 
suggest you use other tools.
David Steffen, Ph.D.
President, Biomedical Computing, Inc. <http://www.biomedcomp.com/>
Phone: (713) 610-9770 FAX: (713) 610-9769 E-mail: steffen@biomedcomp.com

# ===== Want to unsubscribe from this list?
# ===== Send mail with body "unsubscribe" to macperl-request@macperl.org