On Sat, Dec 19, 2009 at 10:03 AM, Bart Van Assche
<bart.vanass...@gmail.com> wrote:
> As known libnetsnmp supports time-based alarms via the functions
> snmp_alarm_register(), run_alarms() and other functions. Two different ways
> to trigger the function run_alarms() are supported inside libnetsnmp:
> 1. By making sure that the timeout argument of select() is small enough such
> that select() returns before the next alarm must be handled (when the
> variable NETSNMP_DS_LIB_ALARM_DONT_USE_SIG is set to one, which is the
> default).
> 2. By making sure that the kernel fires SIGALRM at the time when
> run_alarms() should be called (when the variable
> NETSNMP_DS_LIB_ALARM_DONT_USE_SIG is set to zero, which has to be configured
> explicitly).
>
> The following issues are associated with the second approach:
> 1. Alarm functions are used inside Net-SNMP to e.g. refresh cached table
> contents. As far as I can see there is nothing in the Net-SNMP source code
> that prevents the following from happening: a table refresh triggered via
> SIGALRM while a row is being removed from a cached table. This can result in
> dangling pointer dereferences and even a crash.
> 2. POSIX restricts signal handlers to calling functions that are either
> reentrant or non-interruptible
> (http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04).
> Standard I/O functions like printf() and fprintf() are neither reentrant nor
> non-interruptible. run_alarms() is called from inside a signal handler,
> which means that this restriction applies to the function run_alarms()
> itself and all functions called by it (which includes the alarm callback
> functions). Or: e.g. snmp_log() and its callers must not be called from
> inside run_alarms() when this function is invoked from inside a signal
> handler. This is a severe restriction, and one that is hard to work with.
> 3. Not all software developers know how to make sure that signal delivery
> works correctly in a multithreaded context. POSIX does not guarantee to
> which thread a signal like SIGALRM will be delivered, unless that signal has
> been blocked before thread creation and is unblocked after thread creation
> (see also
> http://www.opengroup.org/onlinepubs/009695399/functions/pthread_sigmask.html).
> This is relevant for the Net-SNMP project not only because a worker thread
> is created inside agent/mibgroup/if-mib/data_access/interface_linux.c but
> also because libnetsnmp is often used inside multithreaded software.
> Currently no attempt is made to make sure that SIGALRM is processed by the
> Net-SNMP event processing loop thread. If SIGALRM is processed by another
> thread, this will result in one or more data races.
>
> Because all the difficulties associated with processing alarms from inside a
> signal handler function, and because fixing these would require more effort
> than it is worth, I propose to remove this feature from the Net-SNMP code
> base and to always use approach (1), whether or not
> NETSNMP_DS_LIB_ALARM_DONT_USE_SIG has been set.

If I do not receive any feedback, I will apply the patch below whithin
a few days. This patch does not modify the behavior of the Net-SNMP
agent itself (snmpd). It only modifies the behavior of applications
linked with libnetsnmp and that set NETSNMP_DS_LIB_ALARM_DONT_USE_SIG
to zero -- for these applications alarm handlers will be called from
inside agent_check_and_process() instead of from the context of
SIGALRM. Applications that set NETSNMP_DS_LIB_ALARM_DONT_USE_SIG to
zero and that did not call run_alarms() (either directly or indirectly
via agent_check_and_process()) will have to be updated -- an explicit
call to run_alarms() will have to be inserted in the socket processing
loop. Enabling SIGALRM based alarm handling by directly calling
set_an_alarm() remains possible.

Index: snmplib/snmp_api.c
===================================================================
--- snmplib/snmp_api.c  (revision 17919)
+++ snmplib/snmp_api.c  (working copy)
@@ -6244,11 +6244,9 @@ snmp_sess_select_info2(void *sessp,
     }
     DEBUGMSG(("sess_select", "\n"));

-    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_ALARM_DONT_USE_SIG)) {
-        next_alarm = get_next_alarm_delay_time(&delta);
-        DEBUGMSGT(("sess_select","next alarm %d.%06d sec\n",
-                   (int)delta.tv_sec, (int)delta.tv_usec));
-    }
+    next_alarm = get_next_alarm_delay_time(&delta);
+    DEBUGMSGT(("sess_select","next alarm %d.%06d sec\n",
+              (int)delta.tv_sec, (int)delta.tv_usec));
     if (next_alarm == 0 && requests == 0) {
         /*
          * If none are active, skip arithmetic.
Index: snmplib/snmp_alarm.c
===================================================================
--- snmplib/snmp_alarm.c        (revision 17919)
+++ snmplib/snmp_alarm.c        (working copy)
@@ -65,22 +65,18 @@
 #include <net-snmp/library/snmp_alarm.h>

 static struct snmp_alarm *thealarms = NULL;
-static int      start_alarms = 0;
 static unsigned int regnum = 1;

 int
 init_alarm_post_config(int majorid, int minorid, void *serverarg,
                        void *clientarg)
 {
-    start_alarms = 1;
-    set_an_alarm();
     return SNMPERR_SUCCESS;
 }

 void
 init_snmp_alarm(void)
 {
-    start_alarms = 0;
     snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                            SNMP_CALLBACK_POST_READ_CONFIG,
                            init_alarm_post_config, NULL);
@@ -422,8 +418,6 @@ snmp_alarm_register(unsigned int when, u
                 (*sa_pptr)->clientreg, (*sa_pptr)->t.tv_sec,
                 ((*sa_pptr)->t.tv_usec / 1000), (*sa_pptr)->flags));

-    if (start_alarms)
-        set_an_alarm();
     return (*sa_pptr)->clientreg;
 }

@@ -492,10 +486,6 @@ snmp_alarm_register_hr(struct timeval t,
                 (*s)->clientreg, (*s)->t.tv_sec, ((*s)->t.tv_usec / 1000),
                 (*s)->flags));

-    if (start_alarms) {
-        set_an_alarm();
-    }
-
     return (*s)->clientreg;
 }
 /**  @} */

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to