views:

586

answers:

1

Our product contains a task-manager system that allows applications to run code in a DLL upon a scheduled interval, specify rules about whether a failure of the task should disable the related application, etc. Mostly it's used for data-upload, data-download, local database maintenance, etc. One of the functions used is to sync the devices time via NTP and set the OS' timezone info. For this, we use OpenNetCF's DateTimeHelper class, which seems to serve as a wrapper around Win32 P/Invokes.

One of the other features of the task manager is that if a task runs longer than its allotted time window, the task manager will Thread.Abort() it to allow other tasks to run. We're seeing an alarming number of thread abortions in which the highest function on the stack is OpenNetCF.WindowsCE.NativeMethods.SetTimeZoneInformation(). Why would the underlying P/Invoke (SetTimeZoneInfo) hang for such a long time?

Our code runs on Windows CE 4.2, and with a much smaller userbase, on Windows CE 5.0 -- the code here is the same between the two versions. So far, I've seen this occur on 4.2 devices but never on 5.0, and even with the smaller number of users on 5.0, I think I would have seen it had it been present there.

The function below is the function from which the problem stems. It converts a time zone abbreviation to its full name, then uses the name to find the right time zone and attempts to set the device's current time zone to that one.

        public static bool SetTimeZone(string timeZoneAbbreviation)
        {
            string TimeZoneInfo = string.Empty;
            bool timeZoneChanged = false;

            switch (timeZoneAbbreviation)
            {
                case ALASKA:
                    TimeZoneInfo = ALASKA_TZN;
                    break;
                case ALASKA_ALT:
                    TimeZoneInfo = ALASKA_TZN;
                    break;
                case ATLANTIC:
                    TimeZoneInfo = ATLANTIC_TZN;
                    break;
                case ATLANTIC_ALT:
                    TimeZoneInfo = ATLANTIC_TZN;
                    break;
                case CENTRAL:
                    TimeZoneInfo = CENTRAL_TZN;
                    break;
                case CENTRAL_ALT:
                    TimeZoneInfo = CENTRAL_TZN;
                    break;
                case EASTERN:
                    TimeZoneInfo = EASTERN_TZN;
                    break;
                case INDIANA:
                    TimeZoneInfo = INDIANA_TZN;
                    break;
                case HAWAII:
                    TimeZoneInfo = HAWAII_TZN;
                    break;
                case MOUNTAIN:
                    TimeZoneInfo = MOUNTAIN_TZN;
                    break;
                case ARIZONA:
                    TimeZoneInfo = ARIZONA_TZN;
                    break;
                case PACIFIC:
                    TimeZoneInfo = PACIFIC_TZN;
                    break;
                case PACIFIC_ALT:
                    TimeZoneInfo = PACIFIC_TZN;
                    break;

                default:                    
                    break;
            }

            TimeZoneInfo += "\0";

            TimeZoneCollection tzc = new TimeZoneCollection();
            tzc.Initialize();

            foreach (TimeZoneInformation tzi in tzc)
            {
                string tzDisplayName = tzi.DisplayName.TrimEnd(new char[]{'\\','0'});

                if (tzDisplayName.ToUpper(CultureInfo.CurrentCulture).Equals(TimeZoneInfo.ToUpper(CultureInfo.CurrentCulture)))
                {
                    DateTimeHelper.SetTimeZoneInformation(tzi);
                    System.Globalization.CultureInfo.CurrentCulture.ClearCachedData();
                    timeZoneChanged = true;
                    break;
                }
            }

            return timeZoneChanged;
        }

Thanks as always for your help. Any thoughts?

A: 

The DateTimeHelper.SetTimeZoneInformation call is a very thin wrapper around a P/Invoke to the SetTimezoneInformation API (I just verified that in the source). It basically makes the call and checks the return code - nothing more, so that pretty much rules out the SDF itself as the root cause.

Next, looking at the MSDN doc for SetTimezoneInformation, it's a really straightforward synchronous call that returns TRUE or FALSE. This tells me that the API is likely not the root cause either.

One thing to remeber in CE is that you can never assume the platform is flawless becasue it's done by the OEM and therefore can have variations. The fact that you see the failure in 4.2 and not 5.0 would lead me to check the following:

  1. Make sure the 4.2 device image has all QFEs applied
  2. See if there is a OS code difference between 4.2 and 5.0 for the timezone stuff (I doubt it, but I don't have PB 4.2 installed any longer).
  3. Check the OEM implementation for setting time. Changing the zone implicitly makes a call to set the time and it's possible there's a bug in the 4.2 BSP that has a potential lock or race that you're hitting.
ctacke
Having looked at the SDF DLL in reflector, I knew it wasn't actually the cause, but put "opennetcf" as a tag just to solicit your comment. =PI'll try the three points below, but the code for SetTimeZoneInfo doesn't seem to be part of the Shared Source (unless I'm misunderstanding...)Thanks!
RJCantrell