Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: ClamAV: devel

libclamav and thread-safety

 

 

ClamAV devel RSS feed   Index | Next | Previous | View Threaded


tony at becrux

Nov 20, 2006, 12:00 PM

Post #1 of 5 (1235 views)
Permalink
libclamav and thread-safety

Hi.

I'm using libclamav in my opensource project, and I've some problems
regarding thread-safety. There's written in the documentation
that clamav library is thread-safe, but I still experience locks.

In order to find out where's the problem, I've written this simple code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <clamav.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct cl_node *root;
int counter = 0;

void *scan(void *arg)
{
const char *virName;
struct cl_limits limits;

memset(&limits, 0, sizeof(struct cl_limits));
limits.maxfiles = 1000;
limits.maxfilesize = 10 * 1048576;
limits.maxreclevel = 5;
limits.maxratio = 200;
limits.archivememlim = 0;

cl_scanfile((char *) arg,&virName,NULL,root,&limits,CL_SCAN_STDOPT);

pthread_mutex_lock(&mutex);
// cl_scanfile((char *) arg,&virName,NULL,root,&limits,CL_SCAN_STDOPT);
--counter;
pthread_mutex_unlock(&mutex);

return NULL;
}

int main(int argc, char *argv)
{
DIR *dirFd;
struct dirent *dirPtr;
pthread_t thId;
pthread_attr_t thAttr;
unsigned int sigNo;
char *buf;

cl_loaddbdir(cl_retdbdir(),&root,&sigNo);
cl_build(root);

pthread_attr_init(&thAttr);
pthread_attr_setdetachstate(&thAttr,PTHREAD_CREATE_DETACHED);

dirFd = opendir(".");
while ((dirPtr = readdir(dirFd)) != NULL)
if (strcmp(dirPtr->d_name,".") && strcmp(dirPtr->d_name,".."))
{
pthread_mutex_lock(&mutex);
++counter;
pthread_mutex_unlock(&mutex);

buf = new char[strlen(dirPtr->d_name)+1];
strcpy(buf,dirPtr->d_name);

pthread_create(&thId,&thAttr,scan,(void *) buf);
}

while (counter)
{
printf("father sleeping, %d\n",counter);
sleep(1);
}

closedir(dirFd);
cl_free(root);

return 0;
}


Don't care about memory leakage. It looks for directory entries and
generates a thread for each entry. Every single thread makes a scan of
his file. Please use a directory with several entries to reproduce test.

Well, if I execute cl_scanfile *outside* the critical section (uncomment
first, comment second), my output is (executed in /usr/bin):

father sleeping, 1241
father sleeping, 1241
father sleeping, 1239
father sleeping, 1239
father sleeping, 1238
father sleeping, 1234
father sleeping, 1234
father sleeping, 1233
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232
father sleeping, 1232


while, if I execute cl_scanfile *inside* critical section (comment
first, uncomment second), the output is:

father sleeping, 219
father sleeping, 177
father sleeping, 173
father sleeping, 133
father sleeping, 110
father sleeping, 110
father sleeping, 110
father sleeping, 110
father sleeping, 103
father sleeping, 87
father sleeping, 71
father sleeping, 52
father sleeping, 42
father sleeping, 42
father sleeping, 23
father sleeping, 23
father sleeping, 23
father sleeping, 10
father sleeping, 3
root [at] asu:/usr/bin#


It seems to me that thread-safety is not respected, and threads get
locked when cl_scanfile is executed simultaneously. Am I missing anything?
Is my code wrong? Do I have to serialize scans?

Thank you so much for your support.

Regards,
Tony.


_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html


clamav-devel at subscriptions

Nov 20, 2006, 1:40 PM

Post #2 of 5 (1174 views)
Permalink
RE: libclamav and thread-safety [In reply to]

On Monday, November 20, 2006 at 12:00 PM, Antonio Di Monaco wrote:
> I'm using libclamav in my opensource project, and I've some problems
> regarding thread-safety. There's written in the documentation
> that clamav library is thread-safe, but I still experience locks.
>
> In order to find out where's the problem, I've written this simple
code:
>
> [test case removed]
>
> Don't care about memory leakage. It looks for directory entries and
> generates a thread for each entry. Every single thread makes a scan of
> his file. Please use a directory with several entries to reproduce
test.
>
> Well, if I execute cl_scanfile *outside* the critical section
(uncomment
> first, comment second), my output is (executed in /usr/bin):
>
> father sleeping, 1241
> [...]
>
>
> while, if I execute cl_scanfile *inside* critical section (comment
> first, uncomment second), the output is:
>
> father sleeping, 219
> [...]
>
> It seems to me that thread-safety is not respected, and threads get
> locked when cl_scanfile is executed simultaneously. Am I missing
anything?
> Is my code wrong? Do I have to serialize scans?

I'm not sure how you conclude that thread-safety is not respected.
Thread-safety would be respected as long as no "damage" is done If
multiple threads attempt to scan at the same time. This could be
achieved by libclamav internally serializing access to any scanning.
Libclamav does much better than this and multiple parallel operations
are indeed possible simultaneously.

The wait loop in the main thread should synchronize access to the
counter variable. Instead of:

> while (counter)
> {
> printf("father sleeping, %d\n",counter);
> sleep(1);
> }

You should probably do:

while (1)
{
pthread_mutex_lock(&mutex);
if (counter == 0)
{
pthread_mutex_unlock(&mutex);
Break;
}
printf("father sleeping, %d\n",counter);
pthread_mutex_unlock(&mutex);
sleep(1);
}

This may or may not change your output, a useful observation of the
benefits of the parallel scanning would be if you reported the runtime
of both tests cases (run several times to be sure that OS caching
doesn't affect what you see).

- Mark Pizzolato

_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html


tony at becrux

Nov 20, 2006, 11:22 PM

Post #3 of 5 (1176 views)
Permalink
RE: libclamav and thread-safety [In reply to]

>I'm not sure how you conclude that thread-safety is not respected.
>Thread-safety would be respected as long as no "damage" is done If
>multiple threads attempt to scan at the same time. This could be
>achieved by libclamav internally serializing access to any scanning.
>Libclamav does much better than this and multiple parallel operations
>are indeed possible simultaneously.
>The wait loop in the main thread should synchronize access to the
>counter variable. Instead of:
>
>> while (counter)
>> {
>> printf("father sleeping, %d\n",counter);
>> sleep(1);
>> }
>
>You should probably do:
>
> while (1)
> {
> pthread_mutex_lock(&mutex);
> if (counter == 0)
> {
> pthread_mutex_unlock(&mutex);
> Break;
> }
> printf("father sleeping, %d\n",counter);
> pthread_mutex_unlock(&mutex);
> sleep(1);
> }
>
>This may or may not change your output, a useful observation of the
>benefits of the parallel scanning would be if you reported the runtime
>of both tests cases (run several times to be sure that OS caching
>doesn't affect what you see).
>

Hi,

thank you for your help :)

I'm not saying that libclamav is not thread-safe, I've no real measure
about that. I'm just making some test cause I've experienced some
locks, and I was trying to find out where's the problem.

I don't agree with you on serializing access to counter variable on
reading. Ok, "real-time" access is not correct regarding true value
of the counter, but, at the end, it has to converge to zero, cause
father is not modifying it, and threads are writing into it correctly.

I've repeated the test, forcing the counter to be "volatile", and I
still
experience that father doesn't exit correctly when threads do multiple
scanning outside critical section (even if I repeat it multiple times).

Everything is fine if I serialize cl_scanfile.

I repeat, maybe I'm misusing libclamav, and, in this case, I'd like
to discover my fault, so I can solve my problem about locks.

Thank you so much for your help, I'll investigate further :)

I appreciate any suggestion you can give me!

Best regards,
Tony.

P.S.: I've tried to apply your solution about counter. Nothing changes :(
_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html


edwintorok at gmail

Nov 21, 2006, 11:23 AM

Post #4 of 5 (1185 views)
Permalink
Re: libclamav and thread-safety [In reply to]

On 11/21/06, Antonio Di Monaco <tony [at] becrux> wrote:
>
> I'm not saying that libclamav is not thread-safe, I've no real measure
> about that. I'm just making some test cause I've experienced some
> locks, and I was trying to find out where's the problem.

Hi,

Which version of clamav are you using?
If you compiled clamav from source, please post you ./configure line.

I've run your test program, with the cvs version in a directory with
~700 files, and everything was fine, the program eventually terminated
(after all files were scanned), and the counter was decrementing.

Best regards,
Edwin
_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html


tony at becrux

Nov 21, 2006, 1:05 PM

Post #5 of 5 (1183 views)
Permalink
Re: libclamav and thread-safety [In reply to]

> Hi,
>
> Which version of clamav are you using?
> If you compiled clamav from source, please post you ./configure line.
Hi,

here is my configure line:

./configure --prefix=/usr --enable-milter --enable-debug
--enable-readdir_r --with-libcurl --with-dbdir=/var/lib/clamav
--enable-bigstack

Hope that it will help :)

Thank you so much for your support!

Regards,
Tony.

_______________________________________________
http://lurker.clamav.net/list/clamav-devel.html

ClamAV devel RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.