diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2026-08-12 23:29:03 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2026-08-12 23:29:03 +0800 |
| commit | 5a86c7a637da1467c9890d31aaccdf4c428dd87d (patch) | |
| tree | acf0748a7e644e3bff5fa25807befbfdf6996773 /lex.cgi | |
| parent | dd2989b86b1a23469165048865945d48a2fd9e7b (diff) | |
| download | lex-5a86c7a637da1467c9890d31aaccdf4c428dd87d.tar.gz | |
Lock-file semaphore for CGI script.
Diffstat (limited to 'lex.cgi')
| -rwxr-xr-x | lex.cgi | 42 |
1 files changed, 39 insertions, 3 deletions
@@ -2,13 +2,14 @@ use strict; use warnings; +use Email::MIME; +use Fcntl qw(:flock); use File::Spec; use File::Find; use File::Path qw(make_path); -use Time::HiRes qw(time); -use Email::MIME; use OpenBSD::Pledge; use OpenBSD::Unveil; +use Time::HiRes qw(time); my $start_time = time(); @@ -43,8 +44,9 @@ unveil("/dev/null", "rw") or die "unveil /dev/null failed: $!"; unveil($base_dir, "rwc") or die "unveil $base_dir failed: $!"; unveil() or die "unveil lock failed: $!"; -pledge('stdio rpath wpath cpath') or die "pledge failed: $!"; +pledge('stdio rpath wpath cpath flock') or die "pledge failed: $!"; +my $dop = 5; my $log_file = "$base_dir/debug.log"; my $max_log_bytes = 1024 * 1024; # 1 MB cap @@ -107,6 +109,40 @@ sub verify_pgp_signature { return $verified ? 1 : 0; } +sub acquire_lock { + my ($max_slots) = @_; + my $lock_dir = "$base_dir/locks"; + + unless (-d $lock_dir) { + make_path($lock_dir) or do { + log_msg("ERROR: Failed to create lock dir $lock_dir: $!"); + return undef; + }; + } + + for my $i (1 .. $max_slots) { + my $slot_file = "$lock_dir/slot_$i.lock"; + my $fh; + + unless (open($fh, '>>', $slot_file)) { + next; + } + + if (flock($fh, LOCK_EX | LOCK_NB)) { + return $fh; + } + close($fh); + } + + return undef; # All slots full +} + +my $lock_fh = acquire_lock($dop); +unless ($lock_fh) { + log_msg("WARN: Concurrency limit ($dop) reached. Dropping request."); + respond_ok(); +} + my $content_type = $ENV{'CONTENT_TYPE'} // ''; my $content_length = $ENV{'CONTENT_LENGTH'} // 0; |
