Problem with Process.GetCurrentProcess() when starting a service

G

Guest

I have written a C# application which should run as a Windows
Service. I must avoid having multiple instances of the application
on one machine so I inserted the following code at the beginning
of the Main() function:

// if this is not the first instance of this application, exit
// immediately. Allow only one instance in the system
if
(Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >
1)
return;

I found out (After few days of struggle) that this code causes the
following problem when trying to start the service by SCM: After
the service is stopped, the next start attempt always fails with
timout. The following start always succeeds. So, every other
service start attempt fails.

I traced the problem to the GetCurrentProcess() function and I got
same result with GetProcesses().

I have created a small C# project to demonstrate the problem. If
you need it for reproduction of the issue, just let me know where
to post it.

Thanks in advance,
 
J

Jeffrey Tan[MSFT]

Hi Benzi,

Based on my understanding, your Windows Service application has included
the listed code snippet to allow only 1 instance of service to run.
However, you find that after stopping your service, you can not restart it
second time with timeout in Services.msc. If I have misunderstood you,
please feel free to tell me, thanks.

What version of .Net Framework you are using, .Net1.1 or 2.0? I have
created a sample Windows Service in VS2005 by adding your listed code
snippet in the main method. However, it can be stopped and restarted
several times without timeout error.

Also, your code logic actually uses the process name as the identity to
implement singleton, which is not always correct, since other applications
may use the same name as your service application, so it will prevent your
service from starting. A better solution is using a named Mutex, which will
become system-wide. See the article below for a sample:
http://www.ai.uga.edu/mc/SingleInstance.html

Additionally, to check if your original process is terminated after
stopping, you may use Task Manager or Process Explorer to examine the
process list.

Finally, if you still can not figure out the root cause, please feel free
to send the sample project to me by removing "online." to get my real email
address.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeffrey,
I'm using .Net 1.1 which could explain the difference. System is Windows XP.

You are generally right that using a process name for setting it as
singleton is not full proof but in the environment where this service runs
it's OK.
Additionally, to check if your original process is terminated after
stopping, you may use Task Manager or Process Explorer to examine the
process list.

The timeout happens even if I wait a long time after the service is stopped
and for sure, the service is not running when I try to start it. Even more,
the timeout happens at the first SCM start attempt after service installation.
Finally, if you still can not figure out the root cause, please feel free
to send the sample project to me

OK. I'm about to do it now.

Thanks for your prompt reply,

--
Benzi Eilon


"Jeffrey Tan[MSFT]" said:
Hi Benzi,

Based on my understanding, your Windows Service application has included
the listed code snippet to allow only 1 instance of service to run.
However, you find that after stopping your service, you can not restart it
second time with timeout in Services.msc. If I have misunderstood you,
please feel free to tell me, thanks.

What version of .Net Framework you are using, .Net1.1 or 2.0? I have
created a sample Windows Service in VS2005 by adding your listed code
snippet in the main method. However, it can be stopped and restarted
several times without timeout error.

Also, your code logic actually uses the process name as the identity to
implement singleton, which is not always correct, since other applications
may use the same name as your service application, so it will prevent your
service from starting. A better solution is using a named Mutex, which will
become system-wide. See the article below for a sample:
http://www.ai.uga.edu/mc/SingleInstance.html

Additionally, to check if your original process is terminated after
stopping, you may use Task Manager or Process Explorer to examine the
process list.

Finally, if you still can not figure out the root cause, please feel free
to send the sample project to me by removing "online." to get my real email
address.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Benzi,

Thanks for your information.

Yes, by creating a VS.net2003 Windows Service project with your code
snippet, I can reproduce the problem. Further research shows that the
problem lies in Process.ProcessName property.

Below is some additional interesting test result:
1. In my 1G RAM machine, I tried to remove the string s =
Process.GetCurrentProcess().ProcessName code into the OnStop() method, I
find that the "stop" command will also experience the timeout problem.
2. On my another 2G RAM machine, I find that when the code is executed in
OnStop method, "stop" command will work well, however, it will still
experience the timeout if I execute the code in main method.

These tests show that my 2G RAM machine has a better hardware performance,
so OnStop method will return timely. However, in OnStart method, since the
OnStart wait period is very short, both 2 machines will fail to return
timely. So it makes sense.

Then I used the VS.net2003 debugger to attach the Windows Service process
while it is hang. By breaking the process while hang several times, I
always got the following managed call stack:

system.dll!System.Diagnostics.PerformanceMonitor.GetData(string item)
Line 1192 + 0xf4 bytes C#

system.dll!System.Diagnostics.PerformanceCounterLib.GetPerformanceData(strin
g item) Line 956 + 0xa8 bytes C#
system.dll!System.Diagnostics.PerformanceCounterLib.get_CategoryTable()
Line 114 + 0x56 bytes C#

system.dll!System.Diagnostics.PerformanceCounterLib.GetPerformanceData(strin
g[] categories, int[] categoryIndexes) Line 941 + 0x3e bytes C#

system.dll!System.Diagnostics.NtProcessManager.GetProcessInfos(System.Diagno
stics.PerformanceCounterLib library) Line 2664 + 0xa3 bytes C#
system.dll!System.Diagnostics.NtProcessManager.GetProcessInfos(string
machineName, bool isRemoteMachine) Line 2636 + 0xa4 bytes C#
system.dll!System.Diagnostics.ProcessManager.GetProcessInfos(string
machineName) Line 2243 + 0x29 bytes C#

system.dll!System.Diagnostics.Process.EnsureState(System.Diagnostics.Process
.State state) Line 1092 + 0x116 bytes C#
system.dll!System.Diagnostics.Process.get_ProcessName() Line 657 + 0x11
bytes C#
dummyservice.exe!DummyService.Service1.Main() Line 33 + 0x12 bytes C#

So, it seems that the .Net1.1 Process.ProcessName property internally uses
PerformanceCounterLib to query the process/thread information. And there is
certain loop calling in the implementation which causes the long
time-consuming.

Then I tried to understand why the .Net2.0 did not experience the hang
timeout issue. In Reflector, it reveals that .Net2.0 changed the
Process.get_ProcessName implementation, which will not use
PerformanceCounterLib internally to query the process/thread information. I
assume that our CLR team has awared of the ProcessName property performance
problem in .Net1.1, so they changed the implementation in .Net2.0.

To workaround this problem, you upgrade your project to the .Net2.0, which
will make the problem go away. Does it meet your need? If you still want to
go with .Net1.1, I think you have to change your implementation to use
Mutex approach.

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeffrey,

Thanks for the detailed explanation. I guess that I have to try the
mutex approach as, according to what you discovered, I can't work
around the problem using ProcessName.

Thanks again,
--
Benzi Eilon


"Jeffrey Tan[MSFT]" said:
Hi Benzi,

Thanks for your information.

Yes, by creating a VS.net2003 Windows Service project with your code
snippet, I can reproduce the problem. Further research shows that the
problem lies in Process.ProcessName property.

Below is some additional interesting test result:
1. In my 1G RAM machine, I tried to remove the string s =
Process.GetCurrentProcess().ProcessName code into the OnStop() method, I
find that the "stop" command will also experience the timeout problem.
2. On my another 2G RAM machine, I find that when the code is executed in
OnStop method, "stop" command will work well, however, it will still
experience the timeout if I execute the code in main method.

These tests show that my 2G RAM machine has a better hardware performance,
so OnStop method will return timely. However, in OnStart method, since the
OnStart wait period is very short, both 2 machines will fail to return
timely. So it makes sense.

Then I used the VS.net2003 debugger to attach the Windows Service process
while it is hang. By breaking the process while hang several times, I
always got the following managed call stack:

system.dll!System.Diagnostics.PerformanceMonitor.GetData(string item)
Line 1192 + 0xf4 bytes C#

system.dll!System.Diagnostics.PerformanceCounterLib.GetPerformanceData(strin
g item) Line 956 + 0xa8 bytes C#
system.dll!System.Diagnostics.PerformanceCounterLib.get_CategoryTable()
Line 114 + 0x56 bytes C#

system.dll!System.Diagnostics.PerformanceCounterLib.GetPerformanceData(strin
g[] categories, int[] categoryIndexes) Line 941 + 0x3e bytes C#

system.dll!System.Diagnostics.NtProcessManager.GetProcessInfos(System.Diagno
stics.PerformanceCounterLib library) Line 2664 + 0xa3 bytes C#
system.dll!System.Diagnostics.NtProcessManager.GetProcessInfos(string
machineName, bool isRemoteMachine) Line 2636 + 0xa4 bytes C#
system.dll!System.Diagnostics.ProcessManager.GetProcessInfos(string
machineName) Line 2243 + 0x29 bytes C#

system.dll!System.Diagnostics.Process.EnsureState(System.Diagnostics.Process
.State state) Line 1092 + 0x116 bytes C#
system.dll!System.Diagnostics.Process.get_ProcessName() Line 657 + 0x11
bytes C#
dummyservice.exe!DummyService.Service1.Main() Line 33 + 0x12 bytes C#

So, it seems that the .Net1.1 Process.ProcessName property internally uses
PerformanceCounterLib to query the process/thread information. And there is
certain loop calling in the implementation which causes the long
time-consuming.

Then I tried to understand why the .Net2.0 did not experience the hang
timeout issue. In Reflector, it reveals that .Net2.0 changed the
Process.get_ProcessName implementation, which will not use
PerformanceCounterLib internally to query the process/thread information. I
assume that our CLR team has awared of the ProcessName property performance
problem in .Net1.1, so they changed the implementation in .Net2.0.

To workaround this problem, you upgrade your project to the .Net2.0, which
will make the problem go away. Does it meet your need? If you still want to
go with .Net1.1, I think you have to change your implementation to use
Mutex approach.

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jeffrey Tan[MSFT]

Hi Benzi,

Yes, since the .Net1.1 Process class internal implementation replies very
much on the PerformanceCounter to query the process/thread information,
there is no way to tell the Process class to workaround the performance
issue. Since using Mutex to implement singleton is a good solution and will
eliminate the performance issue, I recommend you to go with this solution.

Additionally, normally in Windows Service application, you should not place
time-consuming code in the Main method, since the Services.msc will only
wait the Main method to response in a short period. If you really need to
process some length initialization code during service startup, you'd
better spawn another thread to do the work.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top