bsfilterをpop proxyとしてうごかしてmewで読むということをしているのだが、ときどきあるメールで受信が止まってしまうという現象が起きていた。そういうときはbsfilterをとおさずにpopアクセスして問題のメールだけ削除して逃げていたのだが、調べる気になったので調べてみたところ

"invalid byte sequence in EUC-JP"

というメッセージが表示されていた(普段はバックグラウンドでうごかしてメッセージは/dev/nullにすていているので気づいていなかった)。

しらべてみるとbsfilterの「invalid byte sequence in EUC-JP」を回避するというそのものずばりなページがありさっそくパッチを当ててみたが直らず、バックとレースを仕込んでしらべてみたらまた別なところで同様なことがおこっていた。なんだかあちこちscrubを埋め込まないといけない予感がするが、とりあえず問題になったところだけパッチして今回は終了した。

ついでにtimeout関係の書き方が古いらしいのでこれも修正。

% cvs diff
cvs diff: Diffing .
Index: bsfilter
===================================================================
RCS file: /cvsroot/bsfilter/bsfilter/bsfilter,v
retrieving revision 1.87
diff -u -p -r1.87 bsfilter
--- bsfilter    3 Nov 2013 10:22:15 -0000       1.87
+++ bsfilter    26 Feb 2021 09:18:45 -0000
@@ -1243,7 +1243,7 @@ EOM
               ""
             end
           end
-          content = NKF::nkf('-e -X -Z0', content.gsub(/\?(iso-2202-jp|shift-jis)\?/i, '?ISO-2022-JP?'))
+          content = NKF::nkf('-e -X -Z0', content.scrub('?').gsub(/\?(iso-2202-jp|shift-jis)\?/i, '?ISO-2022-JP?'))
         else
           content = latin2ascii(content)
         end
@@ -1368,7 +1368,7 @@ EOM

   def decode_character_reference(str, lang)
     if (@options["utf-8"])
-      newstr = str.gsub(/\&\#(\d{1,5}|x[\da-f]{1,4});/i) do
+      newstr = str.scrub('?').gsub(/\&\#(\d{1,5}|x[\da-f]{1,4});/i) do
         hex_or_dec = $1
         if (hex_or_dec =~ /^x(.*)/i)
           hex_str = $1
@@ -2633,7 +2633,7 @@ EOM
     return if (str =~ /^\A\-ERR/)

     while (str != ".\r\n")
-      timeout(SOCKET_TIMEOUT) do
+      Timeout.timeout(SOCKET_TIMEOUT) do
         pop_proxy_socket.write(str = pop_socket.gets) # forward
       end
     end
@@ -2664,7 +2664,7 @@ EOM
         @options["message-fh"].print(pop_proxy_socket, " is accepted\n") if (@options["verbose"])
         begin
           pop_socket = nil
-          timeout(SOCKET_TIMEOUT) do
+          Timeout.timeout(SOCKET_TIMEOUT) do
             pop_socket = TCPSocket.open(pop_server, pop_port)
           end
           @options["message-fh"].print(pop_socket, " is connected\n") if (@options["verbose"])
@@ -2718,12 +2718,13 @@ EOM
               pop_proxy_socket.write(response.join) # return response to MUA
             end
           end
-        rescue TimeoutError
+        rescue Timeout::Error
           @options["message-fh"].printf("Timeout error %s %s %s\n", pop_server, pop_port, pop_proxy_port) if (@options["verbose"])
-        rescue
+        rescue => e
           @options["message-fh"].printf("pop exception caught %s %s %s\n", pop_server, pop_port, pop_proxy_port) if (@options["verbose"])
           p "#{$!}" if (@options["verbose"])
           p "#{$@}" if (@options["debug"])
+         p e.backtrace
         ensure
           if (pop_proxy_socket && ! pop_proxy_socket.closed?)
             @options["message-fh"].print(pop_proxy_socket, " is gone\n") if (@options["verbose"])
@@ -2894,12 +2895,12 @@ EOM
   def setup_socket_timeout
     TCPSocket.class_eval <<EOM
       def write_timeout(str)
-        timeout(SOCKET_TIMEOUT) do
+        Timeout.timeout(SOCKET_TIMEOUT) do
           return self.write(str)
         end
       end
       def gets_timeout
-        timeout(SOCKET_TIMEOUT) do
+        Timeout.timeout(SOCKET_TIMEOUT) do
           s = self.gets
           if (s == nil)
             raise "socket.gets returned nil"
@@ -2916,12 +2917,12 @@ EOM
   def setup_ssl_socket_timeout
     OpenSSL::SSL::SSLSocket.class_eval <<EOM
       def write_timeout(str)
-        timeout(SOCKET_TIMEOUT) do
+        Timeout.timeout(SOCKET_TIMEOUT) do
           return self.write(str)
         end
       end
       def gets_timeout
-        timeout(SOCKET_TIMEOUT) do
+        Timeout.timeout(SOCKET_TIMEOUT) do
           s = self.gets
           if (s == nil)
             raise "ssl_socket.gets returned nil"

久しぶりにCVSをさわった。体が覚えていたが cvs up -n じゃなくて cvs -n up ということまでは覚えていなかった。