Author Topic: Visual Studio exception (especially with Vista)  (Read 11237 times)

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Visual Studio exception (especially with Vista)
« on: July 24, 2008, 05:47:00 PM »
Hi All

When working with the uTasker simulator an improper use of the routine uEnable_Interrupt() will be flagged by an exception:

// Routine to re-enable interrupts on leaving a critical region
//
void uEnable_Interrupt()                                                 // interrupts are ALWAYS off when entering
{
#ifdef _WINDOWS
    if (!iInterruptLevel) {

        *(int *)0 = 0;                                                   // basic error - cause simulator exception
    }                                                                    // a routine is enabling interrupt although they are presently off. This may not be a serious error but it is unexpected so best check why...
#endif
    if (!(--iInterruptLevel)) {                                          // only when no more interrupt nesting,
#ifndef _WINDOWS
        asm_int_on();
#endif
    }
}


It has been noted by a few users that this has occurred during normal use. See also the following for a case which could quite easily be reprodced:
http://www.utasker.com/forum/index.php?topic=266.0

Since working more with Vista I have found that the occurrence of this increased quite dramatically, so finally I believe that a solution has been found which can easily be applied by everyone using the project.

- First add the patch from the thread above.
- Then add the following:
--    WinSim.c
16.07.2008 Protect main thread from Ethernet frame injections         {24}

    case RX_ETHERNET:
        if (iInitialised) {
#if LOSE_ACKS > 0
            if (fnRandomPacketLoss(LOSE_ACKS)) {
                break;
            }
#endif

            if (iOpSysActive != 0) {                                     // {24}
                return 1;     
            }

            argv[2] = (char *)fnSimulateEthernetIn((unsigned char*)argv[1], *(unsigned short *)argv[0]);
            iRun = 5;                                                    // allow the simulator to treat process frames immediately
        }
        break;


--    WinPcap.cpp
   16.07.2008 Wait before injecting Ethernet frames if the main task is active {1}

        if ( header->len <= LAN_BUFFER_SIZE ) {
            while (main(RX_ETHERNET, ptr) != 0) {                        // {1}
                Sleep(1);
            }

        }
        if (ptr[2]) {
            iRxActivity = 2;
        }


I don't think that I have had a problem since these changes, so try them out too!!

Regards

Mark

Offline freewill78

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Visual Studio exception (especially with Vista)
« Reply #1 on: January 17, 2009, 10:49:17 PM »
I have had the same issue with Windows XP. Above fix seem to correct the issue.

Some Notes:
- My XP using Windows.0 folder. I have also Vista installed on Windows folder. So maybe this explains why my XP has the same problem with Vista.
- As I understand, problem rises because of lost packets, not sure...If that is the problem I think wireless ethernet connection triggers this problem quickly as there are lots of lost packages in WLAN system. I am also using WLAN.

Offline freewill78

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Visual Studio exception (especially with Vista)
« Reply #2 on: January 17, 2009, 10:53:51 PM »
I have still the same problem...I beleive that is WLAN/OS/Driver related...Also after I make a refresh with F5 in windows explorer at ftp page, the uploaded htm files and logos change diferent names and webserver says file not found...

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Visual Studio exception (especially with Vista)
« Reply #3 on: January 17, 2009, 11:46:43 PM »
Hi

>>Also after I make a refresh with F5 in windows explorer at ftp page, the uploaded htm files and logos change diferent names
This bit may be normal due to the operation of the uFileSystem - check here:
http://www.utasker.com/docs/uTasker/uTaskerFileSystem_3.PDF


The exception problem is something which started really showing up with Vista but has been a basic problem for longer (just much less noticeable). It has been improved a lot by the described fix but is not perfect. Some times it is possible to go days or weeks without it happening and some days it can be a bit of a nuisance. The exception is a sort of assertion and so can be commented out and things usually work OK, even when the unexpected event has taken place.

Strangely I had this a couple of days ago two or three times quite close to another and I did start thinking about what I could do to catch the reason again (but didn't stop to attempt analysis since I was in the middle of some work which needed completing). It is not simple since it is due to two threads interrupting each other at a critical moment and it is then complicated to find out exactly where it was in order to protect it properly. Only the WinPCap task can do this and so it happens when Ethernet frames are received at a critical point when this should in fact be blocked. Somehow the blocking is not working correctly...

Just today I decided to try to use the iInterruptLevel variable itself to do this work and made the following change:

- In WinSim.c I modified the following:

Before:
            argv[2] = (char *)fnSimulateEthernetIn((unsigned char*)argv[1], *(unsigned short *)argv[0]);
            iRun = 5; 


After:
            argv[2] = (char *)fnSimulateEthernetIn((unsigned char*)argv[1], *(unsigned short *)argv[0]);
            if (argv[2] == 0) {                                          // {34}
                return 0;                                                // Ethernet frame not for us
            }
            else if (argv[2] == (char *)2) {
                return 1;                                                // Ethernet frame can not be accepted yet since interrupts are blocked
            }
            iRun = 5; 


First of all, any Ethernet frames which are not for us (return 0 since they were filtered) don't cause the scheduler to run, which would also cause any waiting interrupts to be processed - and is consequently potentially dangerous if it gets this far when the main task has blocked interrupts.

Secondly I changed the Ethernet input simulator to return 2 when it detects that the processor's interrupts are blocked (eg by seeing that iInterruptLevel is not 0, or by checking any registers which show it). This then blocks the WinPCap thread until it is safe again.

Since each target package works a little differently in how its frames are actually injected into the Ethernet memory and how it can check the state of the interrupt (some will need a function to call the state since it is local to the target code - not global):


I am sure that the risk of the error increases with network activity (especially without the filter above) but I don't know any relation with Wireless. In fact I don't think that WinPCap can work with a wireless interface (unless newer versions have increased capability?).

You may like to give the patch above a try to see whether it helps at your end. I will be monitoring it and trying my best to improve the situation when I get the chance (unfortunately I tend to get the problem on my Vista PC so infrequently that debugging is rarely possible...)

regards

Mark


Offline freewill78

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Visual Studio exception (especially with Vista)
« Reply #4 on: January 18, 2009, 12:47:36 AM »
Ok. Here is the notes:

FTP is unstable, for example, everytime I select and upload files(htm and gif etc), %50 percantage VC++ stops at

if (!iInterruptLevel) {
        *(int *)0 = 0;                                                   // basic error - cause simulator exception
    }     

and "Copying..." window is there all time as VC++ stopped, and I had to kill task in windows task manager.
I'm not insisting on simulation to evaluate the utasker, I just force my chance as I have free time in the weekend and my hardware at office :(

And especially when overwriting to files it sometimes break here, maybe it gives an idea.

LPC23XXSim.c

  if (iOldLineBlank == 0) {                                // check that we only write 1 to non-blank lines
                    iLineLength = 0;
                    while (iLineLength < FLASH_LINE_SIZE) {
                        if (ucNewLine[iLineLength++] != 0xff) {
                            *(unsigned char *)0 = 0;                     // writing non- '1' to a non-blank line - signal so that this can be corrected
                        }
                    }
                }


- I tried LAN cable instead of WLAN and same issue. So problem looks like not related with WLAN
- I am using XP. I cant try it on Vista, as it is the world worst operating system, with lots of errors and headaches...


« Last Edit: January 18, 2009, 02:20:20 AM by freewill78 »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Visual Studio exception (especially with Vista)
« Reply #5 on: January 18, 2009, 06:13:58 AM »
Hi

In fact there are two things here and the situation is probably not as bad as it seems:

First to the exception in uEnable_Interrupt(). I have found that this is very sensitive in the LPC23xx project, whereas in others not at all. There is a very simple method to get this to occur in the LPC23xx project - simply put a while loop in uDisable_Interrupt() after iInterruptLevel++; (I use about 5000000) and then it happens almost immediately every time there is valid network activity.

I can do the same in a different project and, although the while loop slows things down quite a lot, there is no problem.

After a couple of hours trying to identify what is happening I have not made any progress but the following seems to at least be a work around until the reason can be identified:

    if (!iInterruptLevel) {
        iInterruptLevel = 1;
   //   *(int *)0 = 0;                                                   // basic error - cause simulator exception
    }


Rather than generate an exception to signal that something is not operating as expected, it is repaired. All worked well with this - even though it was being 'repaired' a lot (with the delay)!

I suggest trying the work around so that it doesn't disturb any more.



The second point is not really an error. The FLASH in the LPC23xx (which you are using) is a little complicated - see the following for more details:
http://www.utasker.com/forum/index.php?topic=136.0

The FLASH granularity is rather large at 32k - not that suitable for a small file system. The uTasker uses a method called sub-files to allows small files to be used. It is a bit complicated since it involves each file being accessible using two different file names. One is a sub-file and one is a complete file, with different write and delete characteristics. It is best to read the following document to learn all of the details:
http://www.utasker.com/docs/STR91XF/FileSystemSTR91X.PDF
The document of not for the LPC23xx but for the STR91. The STR91 has 64k granularity, even larger that the LPC23XX's 32k, but the principle is the same. Also you can see the demo files layout in the documents in \Applications\uTaskerV1.3\WebPages\WebPagesLPC23xx\FileSystem

The simulator is trying to operate in exactly the same way as the LPC23xx FLASH does. It can not change individual bits within a line (due to a check sum in the FLASH which will otherwise be corrupted - see link above for description) and when writing to lines which are already programmed, the data should be written with only ones (due to otherwise over-stressing the FLASH) - and the simulator is generating an exception (assert) due to the fact that this is taking place and 'could' cause corruption on the target.

The reason why it is taking place has to do with the sub-file system and the bat file which is copying the files via FTP.
The bat file is copying files with their sub-file names. This allows multiple files to be copied to a single FLASH segment (see doc for full details). This works the first time since the FLASH is empty but will fail if repeated due to the fact that some rules are being broken. In fact this will probably work on the target since breaking rules will not always result in corruption and over-stressing the device will not make it fail (immediately).

The way to work is to use the delete_all.bat to clean the file system and then reload again. This will always work in the simulator (and on the target) since it is not breaking any FLASH programming rules.
When the operation of the sub-file system is understood it is also possible to cause file writes to automatically delete space, but it may mean reloading other files which were sharing the FLASH sector. Therefore it is generally easier to do a full delete.
[In fact if the bat file is written cleverly to cause some files first to be written with their complete file names (to cause sector deletion) and then the others afterwards with their sub-file names it would operate multiple times without breaking rules. But it will be very easy to break it when files are renames so it's not really worth doing this...]

Another tip: The flash content is saved when the simulator is terminated normally. If you want to delete the FLASH content for the next simulation simply delete the file \Applications\uTaskerV1.3\Simulator\FLASH_LPC23XXXX.ini

Final tip: It is possible to configure to use normal file system operation (not sub-file system) by removing SUB_FILE_SIZE. But this is generally not recommended since it is not very efficient with FLASH memory. It will force every file to occupy at least 32k  (one sector) even if it is very small...

Regards

Mark


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Visual Studio exception (especially with Vista)
« Reply #6 on: January 18, 2009, 09:39:58 PM »
Hi

I believe that I have managed to fix this problem. What I found is that the two threads (WinPCap and Simulator) can interrupt each other and so protection is required in two directions. Sometimes, if code is operating in both at the same time, the control actually jumps back and forwards between the two (at least when debugging the case). Interrupt injection can be critical (eg. timer interrupts and Ethernet interrupts) if they can cause handling of the other task to be interrupted at a critical point.

The easiest method to protect any possible interrupt injection was to call the injection routine (all pass via main(int argc, char *argv[]) in WinSimMain.cpp) via an intermediate call _main(int argc, char *argv[]); which waits if the other thread is busy.

Therefore in WinSimMain.cpp all calls of main() were replaced by _main() and _main() looks like this:

// Intermediate call to ensure that the calling thread waits on other active threads
//
static int _main(int argc, char *argv[])                                 // {23}
{
    int iRtn;
    while (WAIT_WHILE_BUSY == (iRtn = main(argc, argv))) {
        Sleep(1);                                                        // yield temporarily until other threads have completed their work
    }
    return iRtn;
}


The define WAIT_WHILE_BUSY was added to WinSim.h [#define WAIT_WHILE_BUSY      0x80000004]

So far so good...

But in the inject code it is also necessary to ensure that the blocking is reliable. This was solved by the following main addition at the beginning of the routine main() in WinSim.c:

    if (iOpSysActive != 0) {                                             // {35}
        return WAIT_WHILE_BUSY;                                          // event can not be handled at the moment so it should wait
    }
    iOpSysActive = 1;                                                    // {36} flag that the simulator is busy


This ensures that, once started, this routine can never be interrupted by a call from another thread. In fact this is a simplification of the previous solution where the flag was specifically set at just some locations. These were this removed and everywhere where the routine could return the following was added:
            iOpSysActive = 0;                                            // {36}

The previously discussed check of the interrupt disable flag in each Ethernet HW simulator is then not necessary, which simplifies and makes the change HW project independent.
The previous change which still applies if the following since it is a more logical solution:

In case RX_ETHERNET
            argv[2] = (char *)fnSimulateEthernetIn((unsigned char*)argv[1], *(unsigned short *)argv[0]);
            if (argv[2] == 0) {                                          // {34}
                iOpSysActive = 0;                                        // {36}
                return 0;                                                // Ethernet frame not for us
            }

            iRun = 5;                                                    // allow the simulator to treat process frames immediately


After short tests with all HW processor targets and artificial interrupt blocking of about 150ms (so that injects occur very regularly at a critical point in time) no problems were encountered. Of course the reaction time of the web server is sluggish but this is expected. Without the artificial delay everything seemed to work as before - but hopefully with no more possibility of the exception being encountered. Only time will tell if this is 100% the case, but I am quite convinced that there will be a useful improvement.

The changes are quite easy to do (by following above). I have also put the changed files to this link:
http://www.uTasker.com/temp/WinSimThreadProtection.zip
They are valid for all projects but I can't guaranty that they will work in every project - there may be other changes which are not completely compatible and so they are there more as a reference in case you would like to try the modifications for your self. Make sure that the change in WinPCap.cpp at the start of this thread is also made. Of course they will be included automatically in future service packs, assuming that there are no negative effects discovered before their next releases.

regards

Mark