Search

Wednesday, April 30, 2008

Ensuring only one instance of an application can be run and then breaking that approach

Whidbey_2005_0409_131710

A question posted on a DL was as follows

"I have an application that allows only one instance on the desktop, how do I force it to open multiple instance for some testing purposes".

Disclaimer: Note that this is kinda hacky and only relevant if you are a tester trying to break something. This shouldn't be treated as a way to achieve anything productive.

Since the user didn't explain which approach is used to ensure only one instance is allowed I'll try listing down the methods I know off and how I can break them.

Using named Mutex:
This is the more resilient approach taken by applications like Windows Media player. Here the application tries to create a named Mutex with sufficiently complicated name to avoid collision. E.g. namespace.app.guid and then try to acquire the mutex. In case it fails to acquire it then an instance is already running and it closes itself. If it acquired the mutex it means it is the first instance and it continues normally. An approach is outlined here.

Even though this seems to be the most robust solution this can be made to fail as well. If an user has sufficient permission he can do a CloseHandle on a Mutex handle created by some other application as well. For this you don't even need to write code. Do the following

  1. Download and install Process Explorer.
  2. Launch it (might need elevation on Vista)
  3. Have an application that uses this approach like my application named SingleInstanceApp.exe. Try launching a second instance and it will fail to open it.
  4. Click on the app finder toolbar button in Process Explorer and drag it to SingleInstanceApp window. This will get this application selected in process explorer.
  5. Select View->Lower Pane View ->Handles or simply Ctrl+H
  6. This will show all the handles created by SingleInstanceApp.
  7. Scroll down looking for the mutexes. At the end the screen looks something as follows Capture
  8. Right click on the mutex and choose Close Handle.
  9. Now try creating the second instance and it will open fine.

Enumerate the names of applications running and see if the app is already running:
This uses a combination of Process.GetCurrentProcess and Process.GetProcessByName(), see an implementation here.

This is easy to break. To do a DOS (Deinal of Service or DOS) just  create another application with the name that the app expects and per-launch it. To open two instances copy the application to another name and open that first and then the original application.

Enumerate Windows

This involves iterating through all the open windows in the system using EnumWindows and then seeing if a Window with a given name or classname is already present. Since the system doesn't guarantee uniqueness in either of the text or class name this can be broken in a similar approach to the first one. However, there are some complications to it as it is difficult to change window text from outside. However, a combination of code injection and SetWindowText win32 API should work.

Tuesday, April 29, 2008

Trivia: How does CLR create a OutOfMemoryException

 

Bargaining

When the system goes out of memory a OutOfMemoryException is thrown. Similarly for stack overflow a StackOverFlorException is thrown. Now typically an exception is thrown as follows (or the corresponding native way)

throw new System.OutOfMemoryException();

But when the system is already out of memory there's a little chance that creating an exception object will succeed. So how does the CLR create these exception objects?


The answer is trivial and as expect, at the very application start it creates all these exception objects and stores them in a static list. In case these exceptions are to be thrown then it is fetched from this list and thrown.


The consequence of handling Stack overflow is even bigger because once the stack has overflown calling even a single method in that thread is equally dangerous and can cause further corruption. That is the material for another post :)

Monday, April 28, 2008

When does the .NET Compact Framework Garbage Collector run

 

Moon

Other than the exact when part this post applies equally for the desktop portion.

Disclaimer: This post is mainly indicative. When the GC runs is an implementation detail and shouldn't be relied on. This is not part of any contract or specification and may (most probably will) change.

The ECMA specification for Garbage Collection is intentionally vague about when an object will be collected (or freed up). The memory management cycle mentioned in the spec is as follows

1. When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
2. If no part of the object can be accessed by any possible continuation of execution, other than the running of finalizers, the object is considered no longer in use and it becomes eligible for finalization. [Note: Implementations might choose to analyze code to determine which references to an object can be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use. end note]
3. Once the object is eligible for finalization, at some unspecified later time the finalizer (§17.12) (if any) for the object is run. Unless overridden by explicit calls, the finalizer for the object is run once only.
4. Once the finalizer for an object is run, if that object, or any part of it, cannot be accessed by any possible continuation of execution, including the running of finalizers, the object is considered inaccessible and the object becomes eligible for collection.
5. Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with that object.

As you can see the specification doesn't even need an implementation to do code analysis to figure out garbage. It can simply use scoping rules (used anyway by the compiler to detect valid variable usage) for garbage detection. The specification also doesn't specify eventually when the objects are collected. The only need is that it is finalized and freed unspecified time later than the time when it goes out of use. This convenient open statement lets each GC implementers to choose whatever they deem fit for the purpose. Since even thread is not specified a concurrent GC or a non-concurrent GC can be used.

However, everyone wants to know exactly when their platform's GC is run. Here goes the non-exhaustive list for the .NET Compact Framework's Garbage Collector

  1. Out of memory condition:
    When the system fails to allocate or re-allocate memory a full GC is run to free up as much as possible and then allocation is re-attempted once more before giving up
  2. After some significant allocation:
    If one megabyte of memory is allocated since the last garbage collection then GC is fired.
  3. Failure of allocating some native resources:
    Internally .NET uses various native resources. Some native resource allocation can fail due to memory issues and GC is run before re-attempting
  4. Profiler:
    Profiler APIs build into the framework can force a GC
  5. Forced GC:
    System.GC class is provided in the BCL to force a collection

Obviously there can be small differences across various platforms on which .NET CF is implemented. However, the differences are small enough to ignore for this discussion.

Even though this list seems small it works pretty well across disparate systems like XBox and Windows Mobile. In the next post I'll try to get into why "production user code should never do a forced GC". I know that statement is a bit controversial (at least it got so in an internal thread).

Wednesday, April 16, 2008

Which end of the egg do you crack. Putting it differently, what is your Endianess

Mr.Egg

Few people seem to know that the word Endianess comes from Gullivers travels. In Gulliver's travel where there were two types of people, the Lilliputs who cracked the small side of their soft boiled eggs and the Blefuscu who used the big side (Big-Endian). Since I'm well networked these days (over Orkut/Facebook/LinkedIn) I make a conscious decision to be Big-Endian while cracking an egg as its the preferred network endianess.

I do not want to delve into the holy endianess war especially because most modern processors allow hardware/software methods to switch it (reminds me of some politicians though :))

However, I do use bit/byte questions as the acid test for fly/no-fly interviews as suggested by this guy. One of them involves asking about the whole endianess business and a code snippet to find out the endianess of the current system. I'm usually looking for something as below

short a = 1;
if (*((char *)&a) == 1)
printf("Little Endian\n");
else
printf("Big Endian\n");
The idea is not to look for an exact code but to ensure that there's no complete ignorance of this area...

Friday, April 11, 2008

Multi-threaded developer

Building....

Once upon a time a kick-ass developer I knew told me that a good developer needs to be multi-threaded and run the following threads

  1. The main worker thread: This is the one used to code up 3-tier applications for your employer. This pays for the rent and for that fancy big car.
  2. The core thread: This is the one that's used to read up data-structures, OS and other fundamental CS stuff which helps you to join into discussion when folks are discussing threaded BST. This also helps you to crack an interview in case you need a new job.
  3. The cool thread: This is the one you use to read up about Silver Light Mobile, ASP.NET MVC Framework, JSON, etc. This keeps you up to date and let's you hang around with other geeks like Scot Hanselman and Don Box

The same person also told me that real programmers do not blog, he asked me "Do you know about Dave Cutler or Linus Torvald's blog?". So I guess we can safely ignore him :)