j wrote:
>
> Hi all ,
>
> I have a cgi but I'd like to limit the number concurrent user for
> this cgi. I am now using `ps -ef | grep -v | grep mycgi | wc -l` and get
> the number and limit it to a number. But I found that this take quite
> some seconds. Is there faster way and safer ways to limit that if
> database is not allowed ?
>
>
> I am thinking of using variable written in a file to record the
> process with some locking mechanism. If the cgi is triggered, the
> variable inside the file is added by one and reduced when the cgi exit.
> But I am worrying if the cgi failed in the middle for whatever reason in
> the middle, the number will be not correctly reflecting the number of
> process.
>
> Can some one suggest a way to provide a more appropriate way or
> solve the above problem ?
Besides the settings file for the httpd, you could write, not the
*number* of processes performing this cgi, but rather the process ids
themselves.

E.g.:

my $count = 0;
open LOCKFILE, "<+", "/absolute/path/to/lockfile.txt"
or die horribly;
$| = 1, select $_ for select LOCKFILE;
TRY_LOOP: {
seek LOCKFILE, 0, SEEK_SET or die horribly;
flock LOCKFILE, LOCK_EX or die horribly;
my pids = split ' ', scalar <LOCKFILE>;
pids = grep kill(0, $_), pids;
if( pids >= 5 ) {
if( ++$count < 10 ) {
flock LOCKFILE, LOCK_UN or die horribly;
fseek LOCKFILE, 0, SEEK_SET or die horribly;
sleep 1; redo TRY_LOOP;
}
print "Status: 503\n";
print "Retry-after: 30\n";
print "Content-type: text/plain\n\n";
print "Our server is overloaded.\n";
print "Please try again in a few minutes.\n"
exit;
}
push pids, $$;
fseek LOCKFILE, 0, SEEK_SET or die horribly;
print LOCKFILE "pids\n" or die horribly;
my $len = tell LOCKFILE;
truncate LOCKFILE, $len;
# explicit unlocking is *usually* a Bad Thing,
# but since $| is 1 for this filehandle, it's ok.
flock LOCKFILE, LOCK_UN or die horribly;
}
END {
flock LOCKFILE, LOCK_EX or die horribly;
my pids = split ' ', scalar <LOCKFILE>;
pids = grep kill(0, $_) && $_ != $$, pids;
seek LOCKFILE, 0, SEEK_SET;
print LOCKFILE "pids\n" or die horribly;
my $len = tell LOCKFILE;
truncate LOCKFILE, $len;
close LOCKFILE or die horribly;
}

[untested]

I probably could have chosen to close the handle after writing our own
pid to the file, and then re-open inside the END block... if the cost of
keeping the handle open for the duration of the cgi is too high (if
you're limited in terms of how many handles your cgi may open), then I
would suggest you do that.

--
$a=24;split//,240513;s/\B/ => /for=qw(ac ab bc ba cb ca
);{push(b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop b))&&redo;}