quahog icon indicating copy to clipboard operation
quahog copied to clipboard

Clamd sometimes returns a NULL response; should be handled

Open jonjo-blur opened this issue 11 years ago • 3 comments

Quahog sometimes receives a NULL response from clamd, and this makes PHP throw a notice:

Undefined offset: 1 in vendor/blurgroup/quahog/src/Quahog/Client.php on line 211

jonjo-blur avatar Jan 20 '14 16:01 jonjo-blur

I just encountered this myself. Here's a simple way to reproduce:

$client->scanStream('asdf');
$client->scanStream('asdf');

The problem appears to be that clamd is not expecting multiple commands on the same connection. Thus, Quahog always fails when multiple commands are issued. Here's another example that produces a different error:

$client->ping();
$client->ping();

The fix is to issue an IDSESSION command before anything else, and close it with END. That's easier said than done, though, because then clamd performs the commands asynchronously.

jchamberlain avatar Sep 15 '14 19:09 jchamberlain

From the clamd man:

       IDSESSION, END
          It  is  mandatory  to  prefix  this command with n or z, and all
          commands inside IDSESSION must be prefixed.
          Start/end a clamd  session.  Within  a  session  multiple  SCAN,
          INSTREAM,  FILDES,  VERSION,  STATS  commands can be sent on the
          same socket without opening new connections. Replies from  clamd
          will be in the form '<id>: <response>' where <id> is the request
          number (in ascii, starting from 1) and <response> is  the  usual
          clamd  reply.   The  reply  lines  have  same  delimiter  as the
          corresponding command had.   Clamd  will  process  the  commands
          asynchronously, and reply as soon as it has finished processing.

So it should be possible to just wait for the correct reply (or error). Or even better, introduce an async mode with non blocking sockets like the docs suggest:

          Clamd  requires  clients to read all the replies it sent, before
          sending  more  commands  to  prevent   send()   deadlocks.   The
          recommended  way  to  implement  a client that uses IDSESSION is
          with non-blocking sockets, and a select()/poll() loop:  whenever
          send  would  block,  sleep  in  select/poll until either you can
          write more data, or read more replies.   Note  that  using  non-
          blocking  sockets  without  the select/poll loop and alternating
          recv()/send() doesn't comply with clamd's requirements.

MassiveHiggsField avatar Dec 07 '16 23:12 MassiveHiggsField

Is the bug still there

cth18012017 avatar Jan 18 '23 22:01 cth18012017