Clamav AntiVirus software source code analysis notes [7]
Hedgehog @ http://blog.csdn.net/littlehedgehog
[Accept loop processing]
I could have finished the main Clamd functions in Article 5 last time, but the thread is not running and the fire is not yet reached. The end of Clamd will be reached.
- If (thr_pool = thrmgr_new (max_threads, idletimeout, scanner_thread) = NULL)
- {
- Logg ("! Thrmgr_new failed/n ");
- Exit (-1 );
- }
- Time (& start_time); // record current time saved in start_time
- For (;;)
- {
- New_sd = accept (socketd, NULL, NULL );
- /* Note that the interrupt will interrupt accept blocking. Here we only need to check whether errno is EINTR. If the returned value is-1 (indicating accpet failure)
- * This is not due to interruption, but to other problems.
- */
- If (new_sd =-1) & (errno! = EINTR ))
- {
- /* Very bad-need to exit or restart */
- # Ifdef HAVE_STRERROR_R
- Logg ("! Accept () failed: % s/n ", strerror_r (errno, buff, BUFFSIZE ));
- # Else
- Logg ("! Accept () failed/n ");
- # Endif
- Continue;
- }
- /* This signal indicates that the terminal is disconnected. We need to re-open the log file */
- If (sighup)
- {
- Logg ("sighup caught: re-opening log file./N ");
- Logg_close ();
- Sighup = 0;
- If (! Logg_file & (CPT = partition OPT (COPT, "logfile ")))
- Logg_file = CPT-> strarg;
- }
- /* Progexit is the identifier that our process receives the SIGINT-Related Signal settings. If it is unfortunate that it is received, we will exit */
- If (! Progexit & new_sd> = 0)
- {
- Client_conn = (client_conn_t *) mmalloc (sizeof (struct client_conn_tag); // here is the userdata parameter for assembling thrmgr_dispatch
- Client_conn-> sd = new_sd; // socket descriptor! This is always used later as a channel for communications between the server and the client.
- Client_conn-> options = options;
- Client_conn-> copt = copt;
- Client_conn-> root = cl_dup (root );
- Client_conn-> root_timestamp = reloaded_time;
- Client_conn-> limits = & limits;
- Client_conn-> mainpid = mainpid;
- If (! Thrmgr_dispatch (thr_pool, client_conn ))
- {
- Close (client_conn-> SD );
- Free (client_conn );
- Logg ("! Thread dispatch failed/N ");
- }
- }
- Pthread_mutex_lock (& exit_mutex );
- If (progexit)
- {
- If (new_sd> = 0)
- {
- Close (new_sd );
- }
- Pthread_mutex_unlock (& exit_mutex );
- Break;
- }
- Pthread_mutex_unlock (& exit_mutex );
- // If self-check is set
- If (selfchk)
- {
- Time (& current_time );
- If (current_time-start_time)> (time_t) selfchk) // This indicates that the time of the virus database exceeds the effective time set by us.
- {
- If (reload_db (root, copt, TRUE) // check whether the database has been changed. if you want to set reload, reload the following nodes.
- {
- Pthread_mutex_lock (& reload_mutex );
- Reload = 1;
- Pthread_mutex_unlock (& reload_mutex );
- }
- Time (& start_time );
- }
- }
- Pthread_mutex_lock (& reload_mutex );
- If (reload)
- {
- Pthread_mutex_unlock (& reload_mutex );
- Root = reload_db (root, COPT, false );
- Pthread_mutex_lock (& reload_mutex );
- Reload = 0;
- Time (& reloaded_time );
- Pthread_mutex_unlock (& reload_mutex );
- # Ifdef clamuko
- If (export OPT (COPT, "clamukoscanonline") | export OPT (COPT, "clamukoscanonaccess "))
- {
- Logg ("Stopping and restarting Clamuko./n ");
- Pthread_kill (clamuko_pid, SIGUSR1 );
- Pthread_join (clamuko_pid, NULL );
- Tharg-> root = root;
- Pthread_create (& clamuko_pid, & clamuko_attr, clamukoth, tharg );
- }
- # Endif
- }
- Else
- {
- Pthread_mutex_unlock (& reload_mutex );
- }
- }
- /* Destroy the thread manager.
- * This waits for all current tasks to end
- */
- Thrmgr_destroy (thr_pool );
Post it here If (thr_pool = thrmgr_new (max_threads, idletimeout, scanner_thread) = NULL)
The main reason is that when we create a thread pool, we have determined the function to be executed by the thread.Scanner_threadYou can look back at the thread pool creation and processing code. The following is to assemble the parameter struct for the thread. The main reason is that the parameter passing form of the thread has been fixed, so we need to load the struct.
The processing function of the thread is only a proxy. The cadres who really do things only have command, as shown below:
- /* Set the main function of the thread to process the job */
- Void scanner_thread (void * Arg)
- {
- Client_conn_t * conn = (client_conn_t *) ARG;
- Sigset_t sigset;
- Int ret, timeout, session = false;
- Struct explain struct * CPT;
- /* Ignore all signals the author has already commented on it. Here it is set to 1, which is actually a blocked signal */
- Sigfillset (& sigset );
- Pthread_sigmask (sig_setmask, & sigset, null); // sets the thread signal shielding code. The semantics is the same as sigprocmask, however, cancel signals that cannot be blocked and restart signals that cannot be responded are protected. Blocked signals are stored in the signal queue and can be taken out by the sigpending () function.
- If (CPT = fig (Conn-> COPT, "readtimeout ")))
- {
- Timeout = cpt-> numarg;
- }
- Else
- {
- Timeout = CL_DEFAULT_SCANTIMEOUT;
- }
- If (! Timeout)
- Timeout =-1;
- Do
- {
- Ret = command (conn-> sd, conn-> root, conn-> limits, conn-> options, conn-> copt, timeout); // This is the real Officer
- If (ret =-1)
- {
- Break;
- }
- Switch (ret)
- {
- Case COMMAND_SHUTDOWN:
- Pthread_mutex_lock (& exit_mutex );
- Progexit = 1;
- Kill (conn-> mainpid, SIGTERM); // here, the Shutdown signal is sent to the main thread, that is, the server process.
- Pthread_mutex_unlock (& exit_mutex );
- Break;
- Case COMMAND_RELOAD:
- Pthread_mutex_lock (& reload_mutex );
- Reload = 1;
- Pthread_mutex_unlock (& reload_mutex );
- Break;
- Case COMMAND_SESSION: // the client sends the command session. We still need to continue to obtain the command loop here (but in what status do we need to send this command)
- Session = TRUE;
- Timeout = 5;
- Break;
- Case COMMAND_END:
- Session = FALSE;
- Break;
- }
- If (session)
- {
- Pthread_mutex_lock (& exit_mutex );
- If (progexit)
- {
- Session = FALSE;
- }
- Pthread_mutex_unlock (& exit_mutex );
- Pthread_mutex_lock (& reload_mutex );
- If (Conn-> root_timestamp! = Reloaded_time)
- {
- Session = false;
- }
- Pthread_mutex_unlock (& reload_mutex );
- }
- }
- While (session );
- Close (Conn-> SD );
- Cl_free (Conn-> root );
- Free (conn );
- Return;
- }
In this way, through command, we shirk the task to other functions to do it. command is the final function, but it will wait for the next time, because the lab is about to close.