flock and sockets

oleg@pobox.com oleg@pobox.com
Thu, 20 Mar 2003 18:28:24 -0800 (PST)


John Hughes wrote:
> I didn't find this when I needed to lock files, so my solution (under
> Unix) was to write a little C code and call it via the FFI. I used a
> single lock file, since my application was a CGI script which runs fairly
> rarely -- there's no need for a finer grain of locking.

Many Linux/Unix systems come with 'procmail' installed. One part of that
installation is a nifty program called 'lockfile':

/tmp> lockfile -h
Usage: lockfile -v | -nnn | -r nnn | -l nnn | -s nnn | -! | -ml | -mu | file...
        -v      display the version number and exit
        -nnn    wait nnn seconds between locking attempts
        -r nnn  make at most nnn retries before giving up on a lock
        -l nnn  set locktimeout to nnn seconds
        -s nnn  suspend nnn seconds after a locktimeout occurred
        -!      invert the exitcode of lockfile
        -ml     lock your system mail-spool file
        -mu     unlock your system mail-spool file

The man page is quite informative. The program is specifically
intended to be used in shell scripts. Therefore, we can use 'lockfile'
in any language system that is capable of executing a shell
command. In Hugs, we can use

> import System (system, ExitCode(ExitSuccess))
> do { system ("lockfile -ml") >>= \ExitSuccess -> print "OK" }

Therefore, we do not have to use FFI, we do not have to compile our
scripts. We can lock files right in Hugs or GHCi.

Daniel Luna wrote:
> The second option that I have is to use a daemon and let the programs that
> get started by mail connect via some sort of socket. Is there any socket
> support in Haskell?

One of the easiest ways of accomplishing this is by using inetd or
xinetd. In this case, your application _only_ needs to read from the
standard input and write into the standard output. An interactive
(that is, not a single request-single reply) daemon should also be
able to flush the standard output or set it to an unbuffered/line
buffered discipline. The application needs to know nothing at all
about sockets. Your network daemon could be just a (uncompiled)
Haskell code, interpreted by Hugs or GHCi.

For example, if you use inetd, you need to get your sysadm to add the
following line

mysrv   13720/tcp    # my service, to listen on port 13720

into /etc/services and the following line

mysrv   stream tcp nowait yourname /home/you/daemon /home/you/daemon 

into /etc/inetd.conf and reHUP the inetd. The file /home/you/daemon
(with executable permissions set) is a start-up shell script

	#!/bin/sh
	cd /home/you/directory
	PATH=right-path
	exec hugs -flags your-script.lhs