0

Might be lock is not working as I expected. Should I use mutes in this case?

Error occurred in following code. On prod it chocked my email server.

Error mail content:

The message is:

Index was outside the bounds of the array.

The Stack trace is:

at System.Collections.Generic.List`1.Add(T item)
at TT.SharedServices.Auditor.Audit.AddAudit(AuditEventType pEvType, Severity pSeverity, Int32 pClientId, String pSessionId, String pDetail, String pClientIp, String pEndUserIp)

The Inner Exception is:

The Request parameters are : sessionID : df58b273-c399-4692-8c14-7400b219769e Details : TimeTaken for LoadAgency:13 ms

 private void AddAudit(AuditEventType pEvType, Severity pSeverity, int pClientId, string pSessionId, string pDetail,
                    string pClientIp, string pEndUserIp)
 {
     // TO DO: also add Time
     Trace.TraceInformation("Audit.Add entered : ");
     try
     {
         if (pSeverity == Severity.High || Convert.ToBoolean(ConfigurationSystem.SharedApiConfig[pSeverity.ToString().ToLower()])) // chk option in config for adding audit
         {
             if (string.IsNullOrEmpty(pDetail))
             {
                 throw new ArgumentException("Detail should have a value", "pDetail");
             }
             // adding data
             var paramList = new DbParameter[8];
             paramList[0] = DataAccess.ParameterFactory.Create("@eventType", DbType.Int16, pEvType);
             paramList[1] = DataAccess.ParameterFactory.Create("@severity", DbType.Int16, pSeverity);
             paramList[2] = DataAccess.ParameterFactory.Create("@clientId", DbType.String, pClientId);
             paramList[3] = DataAccess.ParameterFactory.Create("@detail", DbType.String, pDetail);

             if (string.IsNullOrEmpty(pClientIp))
                 paramList[4] = DataAccess.ParameterFactory.Create("@clientIP", DbType.String, DBNull.Value);
             else
                 paramList[4] = DataAccess.ParameterFactory.Create("@clientIP", DbType.String, pClientIp);

             if (string.IsNullOrEmpty(pEndUserIp))
                 paramList[5] = DataAccess.ParameterFactory.Create("@endUserIP", DbType.String, DBNull.Value);
             else
                 paramList[5] = DataAccess.ParameterFactory.Create("@endUserIP", DbType.String, pEndUserIp);

             if (string.IsNullOrEmpty(pSessionId))
                 paramList[6] = DataAccess.ParameterFactory.Create("@sessionId", DbType.String,
                                                                   new Guid().ToString());
             else
                 paramList[6] = DataAccess.ParameterFactory.Create("@sessionId", DbType.String, pSessionId);

             paramList[7] = DataAccess.ParameterFactory.Create("@eventTime", DbType.DateTime, DateTime.Now);
             if (IsBulkAuditSharedApi)
             {
                 _auditQueueData.Add(paramList);
                 if (_auditQueueData.Count > MaxCountSharedApi)
                 {
                     AuditThreadData threadData = new AuditThreadData();
                     lock (_auditQueueData)
                     {
                         threadData.Audit = new List<DbParameter[]>();
                         threadData.Audit = _auditQueueData;
                         _auditQueueData = new List<DbParameter[]>();
                     }                           
                     Thread callAuditPush = new Thread(AuditPushThread);
                     callAuditPush.Start(threadData);
                 }
             }
             else
             {
                 int rowsAffected = DataAccess.ExecuteNonQuery(SpNames.IAPI_AddAudit, paramList);
                 Trace.TraceInformation("Audit.Add : Adding Audit data. rowsAffected = " + rowsAffected);
             }
             Trace.TraceInformation("Audit.Add exit : ");
         }
     }
     catch (Exception exception)
     {                
         string auditText = "The message is :" + exception.Message + "<br/> The Stack trace is :" + exception.StackTrace;
         auditText += "<br/> The Inner Exception is:" + exception.InnerException;
         auditText += "<br/> The Request parameters are : \n sessionID : " + pSessionId + "\n Details : " + pDetail;
         Email.Email.SendingErrorEmail("Exception in Adding Audit in IAPI :", auditText, true, Email.Email.EmailSeverity.Error);
     }
}


    struct AuditThreadData
    {
        internal List<DbParameter[]> Audit;
    }
    #region Private Static Methods
    /// <summary>
    /// This method will Audit the data(in Bulk) in DB
    /// </summary>
    /// <param name="objData"></param>
    private void AuditPushThread(object objData)
    {
        try
        {
            var data = (AuditThreadData)objData;
            if (data.Audit != null && data.Audit.Count > 0)
            {
                foreach (var paramList in data.Audit)
                {
                    if (DataAccess != null) DataAccess.ExecuteNonQuery(SpNames.IAPI_AddAudit, paramList);
                }
            }
        }
        catch (Exception ex)
        {
            // catch block for precaution. 
            try
            {
                var log = new EventLog {Source = "Application"};
                log.WriteEntry("Bulk audit add failed:" + ex.Message + ex.InnerException, EventLogEntryType.Error, 2344);                    
            }
            catch
            {
                // to handle system security crash while writing log
            }
        }
    }
Rohit
  • 300
  • 2
  • 14
  • You don't seem to be doing anything with `_auditQueueData` which requires a lock on it, however you are outside the lock with `_auditQueueData.Add(paramList);`. Hard to understand without seeing more of the context of the code – CodingIntrigue Jan 22 '14 at 08:15

1 Answers1

0

You call _auditQueueData.Add(paramList); outside of the lock. Try to put it inside.

Also you lock to the List itself, while ICollections (like List) have a SyncRoot property which exists for this very purpose. This property might be used by other parts of the framework like the UI. You need to explicitly cast your List to ICollection to access this property.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
HDW
  • 16