漏れならブロックにラベルをつけて一気に抜けるがなぁ
WRITE_IPLOG: {
  open my $fh, '+>>', 'log.dat' # my $fhは5.6以降。5.005以前に対応するならIO::File
    or die $!;
  flock $fh, 2;
  seek $fh, 0, 0; # a+を適切にサポートしていないプラットフォームでは必要
  while (my $read = <$fh>) {
    chomp $read;
    last WRITE_IPLOG if $read eq $ipaddr;
  }
  print $fh $ipaddr, "\n";
} # スコープアウトで$fhは自動で閉じられる