Hi Lennart,

Creating macro is a temporary solution. Later, I hope IMM should provide
other immutil utility 
which do same things but thread-safe. As now, most SAF services have
multiple threads.

To verify the macro work correctly, I used GCC with option "-E" to generate
pre-processing code.
E.g:
me@:~/opensaf/opensaf-staging/osaf/services/saf/logsv/lgs$ touch
lgs_imm_gcfg.cc
me@:~/opensaf/opensaf-staging/osaf/services/saf/logsv/lgs$ make
AM_DEFAULT_VERBOSITY=1

Then, generate the pre-processing code by using the same command for
compiler lgs_imm_gcfg.cc, but using "-E" option.

Regarding your proposal, I am afraid of applying the "standard" solution to
LOG now could be high risk.
To avoid using macro, other way, is to not using immutil in
`applier_thread`, but calling to IMM API directly
and create our own retry mechanism in `applier_thread`.

How about your idea?

Regards, Vu.

>-----Original Message-----
>From: Lennart Lund [mailto:[email protected]]
>Sent: Friday, May 13, 2016 3:26 PM
>To: Vu Minh Nguyen; [email protected]
>Cc: [email protected]; Lennart Lund
>Subject: RE: [PATCH 1 of 1] log: make using immutilWrapperProfile thread
safe
>[#1807]
>
>Hi Vu,
>
>The ticket points out a problem that has to be fixed and your patch is a
>solution that probably will work (I have not tested) but...
>We should not create new macros since they do create problems e.g. not
clean
>code, may hide problems that could have been detected by compiler etc.
Also,
>we shall follow the Google style guide that says that macros shall be
avoided
>(also explains why).
>
>The "standard" solution in OpenSAF for handling immutil (see e.g. smf) is
to
>setup the immutilWrapperProfile during init of service before any threads
are
>created and after that the immutilWrapperProfile is never changed. To do
this
>is log service should work. In some places changes of immutilWrapperProfile
>must be removed and in places when an abort is wanted if not SA_AIS_OK it
>must be handled in place and not letting immutil do that.
>
>Thanks
>Lennart
>
>> -----Original Message-----
>> From: Vu Minh Nguyen [mailto:[email protected]]
>> Sent: den 11 maj 2016 12:32
>> To: [email protected]; Lennart Lund
>> Cc: [email protected]
>> Subject: [PATCH 1 of 1] log: make using immutilWrapperProfile thread safe
>> [#1807]
>>
>>  osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc |  110 ++++++++++++++++-----
>> ------
>>  osaf/services/saf/logsv/lgs/lgs_util.cc     |   18 ++++
>>  osaf/services/saf/logsv/lgs/lgs_util.h      |   46 +++++++++++
>>  3 files changed, 130 insertions(+), 44 deletions(-)
>>
>>
>> LOG has several threads which were using same global
>> `immutilWrapperProfile` variable
>> when invoking `immutil_` utility. This caused race condition.
>>
>> This patch created an macro which have same functionalities as `immutil_`
>> does,
>> but thread safe. This macro is used by `applier_thread`, the main thread
is
>> still using `immutil`. By this way, there is no race condition in
>> using `immutilWrapperProfile` between main thread and `applier_thread`.
>>
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
>> b/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
>> @@ -31,6 +31,7 @@
>>  #include "osaf_time.h"
>>  #include "osaf_poll.h"
>>
>> +#include "lgs_util.h"
>>  /*
>>   * Implements an IMM applier for the OpensafConfig class.
>>   * Used for detecting changes of opensafNetworkName attribute.
>> @@ -117,8 +118,6 @@ typedef enum {
>>
>>  static th_state_t th_state = TH_NOT_STARTED;
>>
>> -extern struct ImmutilWrapperProfile immutilWrapperProfile;
>> -
>>
>> /**********************************************************
>> ********************
>>   * Outside applier thread
>>
>> **********************************************************
>> ********************/
>> @@ -610,13 +609,23 @@ static int read_network_name()
>>       * Initialize an IMM object manager
>>       */
>>      // Wait up to 500ms
>> -    immutilWrapperProfile.errorsAreFatal = 0;
>> -    immutilWrapperProfile.nTries = 500;
>> -    immutilWrapperProfile.retryInterval = 1000;
>> +    ImmutilWrapperProfile_t profile;
>> +    profile.errorsAreFatal = 0;
>> +    profile.nTries = 500;
>> +    profile.retryInterval = 1000;
>>
>> -    ais_rc = immutil_saImmOmInitialize(&om_handle, NULL,
>> &immVersion);
>> +    SaVersionT localVer = immVersion;
>> +    ais_rc = saImmOmInitialize(&om_handle, NULL,
>> &immVersion);
>> +    unsigned int nTries = 1;
>> +    while (ais_rc == SA_AIS_ERR_TRY_AGAIN
>> +           && nTries < profile.nTries) {
>> +            usleep(profile.retryInterval * 1000);
>> +            localVer = immVersion;
>> +            ais_rc = saImmOmInitialize(&om_handle, NULL,
>> &localVer);
>> +            nTries++;
>> +    }
>>      if (ais_rc != SA_AIS_OK) {
>> -            TRACE("immutil_saImmOmInitialize FAIL %s",
>> saf_error(ais_rc));
>> +            TRACE("saImmOmInitialize FAIL %s",
>> saf_error(ais_rc));
>>              rc = -1;
>>              goto done;
>>      }
>> @@ -627,15 +636,14 @@ static int read_network_name()
>>      /* Find the opensafNetworkName attribute in the
>> OpensafConfig object and
>>       * get its value
>>       */
>> -    ais_rc = immutil_saImmOmSearchInitialize_2(
>> -            om_handle,
>> -            NULL,
>> -            SA_IMM_SUBTREE,
>> -            SA_IMM_SEARCH_ONE_ATTR |
>> SA_IMM_SEARCH_GET_SOME_ATTR,
>> -            &searchParam,
>> -            attributeNames,
>> -            &searchHandle
>> -            );
>> +    ais_rc = IMMUTIL_F(profile, saImmOmSearchInitialize_2,
>> +                       om_handle,
>> +                       NULL,
>> +                       SA_IMM_SUBTREE,
>> +                       SA_IMM_SEARCH_ONE_ATTR |
>> SA_IMM_SEARCH_GET_SOME_ATTR,
>> +                       &searchParam,
>> +                       attributeNames,
>> +                       &searchHandle);
>>      if (ais_rc != SA_AIS_OK) {
>>              TRACE("immutil_saImmOmSearchInitialize_2
>> FAIL %s", saf_error(ais_rc));
>>              rc = -1;
>> @@ -645,7 +653,11 @@ static int read_network_name()
>>      /*
>>       * Get the value for the searched attribute
>>       */
>> -    ais_rc = immutil_saImmOmSearchNext_2(searchHandle,
>> &object_name, &attributes);
>> +    ais_rc = IMMUTIL_F(profile,
>> +                       saImmOmSearchNext_2,
>> +                       searchHandle,
>> +                       &object_name,
>> +                       &attributes);
>>      if (ais_rc != SA_AIS_OK) {
>>              TRACE("immutil_saImmOmSearchNext_2 FAIL
>> %s", saf_error(ais_rc));
>>              rc = -1;
>> @@ -671,7 +683,7 @@ static int read_network_name()
>>
>>  done:
>>      /* Finalize search */
>> -    ais_rc = immutil_saImmOmFinalize(om_handle);
>> +    ais_rc = IMMUTIL_F(profile, saImmOmFinalize, om_handle);
>>      if ((ais_rc != SA_AIS_OK) && (ais_rc !=
>> SA_AIS_ERR_BAD_HANDLE)) {
>>              /* BAD HANDLE is not a fault here since finalize
>> is called
>>               * also if initialize failed
>> @@ -723,7 +735,7 @@ static int applier_init(SaImmOiHandleT *
>>      if (th_do_cancel()) {
>>              TRACE("Canceled at 1");
>>              /* Cancellation point no error */
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      /* Finalize applier OI handle if needed */
>> @@ -732,47 +744,56 @@ static int applier_init(SaImmOiHandleT *
>>      if (th_do_cancel()) {
>>              TRACE("Canceled at 2");
>>              /* Cancellation point no error */
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      // Wait up to 500ms
>> -    immutilWrapperProfile.errorsAreFatal = 0;
>> -    immutilWrapperProfile.nTries = 500;
>> -    immutilWrapperProfile.retryInterval = 1000;
>> +    ImmutilWrapperProfile_t profile;
>> +    profile.errorsAreFatal = 0;
>> +    profile.nTries = 500;
>> +    profile.retryInterval = 1000;
>>
>>      /* Initialize OI for applier and get OI handle */
>> -    ais_rc = immutil_saImmOiInitialize_2(imm_appl_hdl,
>> &callbacks, &immVersion);
>> +    ais_rc = saImmOiInitialize_2(imm_appl_hdl, &callbacks,
>> &immVersion);
>> +    SaVersionT localVer = immVersion;
>> +    unsigned int nTries = 1;
>> +    while (ais_rc == SA_AIS_ERR_TRY_AGAIN
>> +           && nTries < profile.nTries) {
>> +            usleep(profile.retryInterval * 1000);
>> +            localVer = immVersion;
>> +            ais_rc = saImmOiInitialize_2(imm_appl_hdl,
>> &callbacks, &immVersion);
>> +            nTries++;
>> +    }
>>      if (ais_rc != SA_AIS_OK) {
>> -            LOG_WA("immutil_saImmOiInitialize_2 Failed
>> %s", saf_error(ais_rc));
>> +            LOG_WA("saImmOiInitialize_2 Failed %s",
>> saf_error(ais_rc));
>>              rc = -1;
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      if (th_do_cancel()) {
>>              TRACE("Canceled at 3");
>>              /* Cancellation point no error */
>>              applier_finalize(*imm_appl_hdl);
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      /* Get selection object for event handling */
>> -    ais_rc = immutil_saImmOiSelectionObjectGet(*imm_appl_hdl,
>> imm_appl_selobj);
>> +    ais_rc = IMMUTIL_F(profile, saImmOiSelectionObjectGet,
>> *imm_appl_hdl, imm_appl_selobj);
>>      if (ais_rc != SA_AIS_OK) {
>>              LOG_WA("immutil_saImmOiSelectionObjectGet
>> Failed %s", saf_error(ais_rc));
>>              applier_finalize(*imm_appl_hdl);
>>              imm_appl_hdl = 0;
>>              rc = -1;
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      if (th_do_cancel()) {
>>              TRACE("Canceled at 3");
>>              /* Cancellation point no error */
>>              applier_finalize(*imm_appl_hdl);
>> -            goto done;
>> +            return rc;
>>      }
>>
>> -done:
>>      TRACE_LEAVE2("rc = %d", rc);
>>      return rc;
>>  }
>> @@ -800,31 +821,32 @@ static int applier_set_name_class(SaImmO
>>              TRACE("Canceled at 1");
>>              /* Cancellation point no error */
>>              applier_finalize(imm_appl_hdl);
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      /* Become applier */
>> -    immutilWrapperProfile.errorsAreFatal = 0;
>> -    immutilWrapperProfile.nTries = 500;
>> -    immutilWrapperProfile.retryInterval = 1000;
>> +    ImmutilWrapperProfile_t profile;
>> +    profile.errorsAreFatal = 0;
>> +    profile.nTries = 500;
>> +    profile.retryInterval = 1000;
>>
>> -    ais_rc = immutil_saImmOiImplementerSet(imm_appl_hdl,
>> applier_name);
>> +    ais_rc = IMMUTIL_F(profile, saImmOiImplementerSet,
>> imm_appl_hdl, applier_name);
>>      if (ais_rc != SA_AIS_OK) {
>>              LOG_WA("immutil_saImmOiImplementerSet
>> Failed %s", saf_error(ais_rc));
>>              applier_finalize(imm_appl_hdl);
>>              rc = -1;
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      if (th_do_cancel()) {
>>              TRACE("Canceled at 2");
>>              /* Cancellation point no error */
>>              applier_finalize(imm_appl_hdl);
>> -            goto done;
>> +            return rc;
>>      }
>>
>>      /* Become class implementer (applier) for the OpensafConfig
>> class */
>> -    ais_rc =
>> immutil_saImmOiClassImplementerSet(imm_appl_hdl, gcfg_class);
>> +    ais_rc = IMMUTIL_F(profile, saImmOiClassImplementerSet,
>> imm_appl_hdl, gcfg_class);
>>      if (ais_rc != SA_AIS_OK) {
>>
>>      LOG_WA("immutil_saImmOiClassImplementerSet Failed %s",
>> saf_error(ais_rc));
>>              applier_finalize(imm_appl_hdl);
>> @@ -852,7 +874,6 @@ done:
>>  static void applier_finalize(SaImmOiHandleT imm_appl_hdl)
>>  {
>>      SaAisErrorT ais_rc = SA_AIS_OK;
>> -
>>      TRACE_ENTER();
>>
>>      /* Finalize applier OI handle if needed */
>> @@ -860,11 +881,12 @@ static void applier_finalize(SaImmOiHand
>>              /* We have a handle to finalize */
>>              TRACE("saImmOiFinalize");
>>
>> -            immutilWrapperProfile.errorsAreFatal = 0;
>> -            immutilWrapperProfile.nTries = 500;
>> -            immutilWrapperProfile.retryInterval = 1000;
>> +            ImmutilWrapperProfile_t profile;
>> +            profile.errorsAreFatal = 0;
>> +            profile.nTries = 500;
>> +            profile.retryInterval = 1000;
>>
>> -            ais_rc =
>> immutil_saImmOiFinalize(imm_appl_hdl);
>> +            ais_rc = IMMUTIL_F(profile, saImmOiFinalize,
>> imm_appl_hdl);
>>              if (ais_rc != SA_AIS_OK) {
>>                      TRACE("immutil_saImmOiFinalize
>> Failed %s", saf_error(ais_rc));
>>              }
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_util.cc
>> b/osaf/services/saf/logsv/lgs/lgs_util.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_util.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_util.cc
>> @@ -48,6 +48,24 @@
>>  #define LOG_TAIL_MAX
>> (std::string("_yyyymmdd_hhmmss_yyyymmdd_hhmmss.log").size())
>>
>>  /**
>> + * Report to stderr and syslog and abort process
>> + * @param fmt
>> + */
>> +void logError(char const *fmt, ...)
>> +{
>> +    va_list ap;
>> +    va_list ap2;
>> +
>> +    va_start(ap, fmt);
>> +    va_copy(ap2, ap);
>> +    vfprintf(stderr, fmt, ap);
>> +    vsyslog(LOG_ERR, fmt, ap2);
>> +    va_end(ap2);
>> +    va_end(ap);
>> +    abort();
>> +}
>> +
>> +/**
>>   * Create config file according to spec.
>>   * @param root_path[in]
>>   * @param stream[in]
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_util.h
>> b/osaf/services/saf/logsv/lgs/lgs_util.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_util.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_util.h
>> @@ -29,6 +29,7 @@
>>
>>  #include "lgs_stream.h"
>>  #include "lgs_evt.h"
>> +#include "immutil.h"
>>
>>  /*
>> ==========================================================
>> ==============
>>   *   DEFINITIONS
>> @@ -40,11 +41,55 @@
>>  #define CFG_EXP_FIXED_LOG_REC_SIZE "FIXED_LOG_REC_SIZE:"
>>  #define CFG_EXP_LOG_FULL_ACTION "LOG_FULL_ACTION:"
>>
>> +/**
>> + * This macro is used to generate the retry machanism
>> + * which has the same effects as immutil_ utility, but thread safe.
>> + *
>> + * @param P ImmutilWrapperProfile_t
>> + * @param F IMM API
>> + * @param ... Arguments to IMM API
>> + * @return return the AIS error code
>> + *
>> + * NOTE:
>> + * This macro is not applied for saImmOmInitialize()/saImmOiInitialize()
>> + */
>> +#define IMMUTIL_F(P, F, ...)
>>                      \
>> +    ({
>>                              \
>> +    SaAisErrorT ais_ret_m = F(__VA_ARGS__);
>>                      \
>> +    unsigned int nTries_m = 1;
>>              \
>> +    while (ais_ret_m == SA_AIS_ERR_TRY_AGAIN
>>              \
>> +           && nTries_m < P.nTries) {
>>              \
>> +            usleep(P.retryInterval * 1000);
>>                      \
>> +            ais_ret_m = F(__VA_ARGS__);
>>                      \
>> +            nTries_m++;
>>                      \
>> +    }
>>                              \
>> +    if (ais_ret_m != SA_AIS_OK && P.errorsAreFatal)
>>              \
>> +            logError("(%s) %s FAILED, rc = %d", __func__,
>> #F, (int) ais_ret_m); \
>> +    ais_ret_m;
>>                      \
>> +    })
>> +
>>  /*
>> ==========================================================
>> ==============
>>   *   TYPE DEFINITIONS
>>   *
>> ==========================================================
>> ==============
>>   */
>>
>> +/**
>> + * Controls the behavior of the wrapper functions.
>> + */
>> +typedef struct lgs_ImmutilWrapperProfile {
>> +    int errorsAreFatal;
>> +    /**< If set the calling program is aborted on an error return
>> from SAF.  */
>> +    unsigned int nTries;
>> +    /**< Number of tries before we give up.  */
>> +    unsigned int retryInterval;
>> +    /**< Interval in milli-seconds between tries.  */
>> +    lgs_ImmutilWrapperProfile() {
>> +            errorsAreFatal = 1;
>> +            nTries = 5;
>> +            retryInterval = 400;
>> +    }
>> +} ImmutilWrapperProfile_t;
>> +
>>  /*
>> ==========================================================
>> ==============
>>   *   DATA DECLARATIONS
>>   *
>> ==========================================================
>> ==============
>> @@ -80,5 +125,6 @@ bool lgs_is_valid_pathlength(const std::
>>  /* Timer functions */
>>  int lgs_init_timer(time_t timeout_s);
>>  void lgs_close_timer(int ufd);
>> +void logError(char const *fmt, ...);
>>
>>  #endif   /* ifndef __LGS_UTIL_H */


------------------------------------------------------------------------------
Mobile security can be enabling, not merely restricting. Employees who
bring their own devices (BYOD) to work are irked by the imposition of MDM
restrictions. Mobile Device Manager Plus allows you to control only the
apps on BYO-devices by containerizing them, leaving personal data untouched!
https://ad.doubleclick.net/ddm/clk/304595813;131938128;j
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to