New-Hardlink hangs if called within event

Topics: Developer Forum, User Forum
May 13, 2010 at 12:00 PM

I use to have simple PowerShell based file monitor, which creates hardlink to the new file in the working directory.

Originally the script was using PowerShell 1.0, PSEventing and PSCX 1.2. Recently I've successfully migrated to PowerShell 2.0 and removed PSEventing dependency.

Two days ago I've performed another upgrade by moving to PSCX 2.0, which should not even require changes in the script since import happens in the profile. Unfortunately I've faced really strange error. Any attempt to call New-HardLink within the even results in hanging. Below snippet illustrates problem in simplest way (just change second line, run script  (from the different directory) and rename any file in the specified directory).

The New-HardLink cmdlet if called not from the event works fine. I'm quite puzzled of this behaviour (as the experiment I've replaced the New-Hardlink with Import-Module PSCX with the same effect).

===========================================

$fsw = new-object system.io.filesystemwatcher;
$fsw.Path = "C:\Users\Public";
$fsw.NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite';
$job = Register-ObjectEvent $fsw Renamed -Action {
  $path = $Event.SourceEventArgs.FullPath;
  $name = $Event.SourceEventArgs.Name;
  Write-Host $name;
  Write-Host $path;
  New-Hardlink $name $path;
  }
$job.Id;
===========================================

Developer
May 14, 2010 at 2:33 AM

interesting ... i'll investigate this.

Jun 29, 2010 at 4:18 PM

Have you have any luck troubleshooting this issue?

I've yesterday have revisited the problem and having slighly more time narrowed it down to creation of Pipeline invocation in line:117 of PipelineHelper.cs. The threads are getting deadlocked because the default Runspace has been used for pipeline and at the same time the other thread (most probably the job thread itself) is using the pipeline in the same runspace.

Interestingly if I run simple pipeline within job (i.e. Write-Output "Test" | Write-Host;) deadlock does not occur.

Any comments?

Investigation continues....

Jun 29, 2010 at 4:50 PM

I believe the current concurrent condition can be resolved by using runspace pool (Powershell.RunspacePool) or creating nested powershell object (Powershell.CreateNestedPowerShell).

I'll try this and update.

Coordinator
Jun 29, 2010 at 5:06 PM

Thanks for debugging this.  Summer can be a tough time to stay indoors debugging software in your spare time.  :-)

Jun 29, 2010 at 6:03 PM
Edited Jun 29, 2010 at 6:06 PM

I’m stuck again – both RunspacePool and CreateNestedPowerShell require PowerShell object.

Developer
Jun 30, 2010 at 2:01 AM

This is one of those things where your cmdlet needs a pipeline, but it can't tell if it needs a Pipeline or a NestedPipeline

Developer
Jun 30, 2010 at 5:03 PM
If you're in a PSCmdlet instance, you should assume you need a nested pipeline, right? The PSCmdlet wouldn't be executing if there was no pipeline...
 
-Oisin

On Tue, Jun 29, 2010 at 10:01 PM, Jaykul <notifications@codeplex.com> wrote:

From: Jaykul

This is one of those things where your cmdlet needs a pipeline, but it can't tell if it needs a Pipeline or a NestedPipeline

Read the full discussion online.

To add a post to this discussion, reply to this email (Pscx@discussions.codeplex.com)

To start a new discussion for this project, email Pscx@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com




--

---
404 signature missing
Jun 30, 2010 at 5:51 PM

In this scenario NestedPipeline of DefaultRunspace is used and effect is known - DEADLOCK.

Any idea how this could be handled to avoid deadlock?

Developer
Jun 30, 2010 at 10:21 PM

Yeah, just verified the deadlock. That's unexpected, and annoying. Our PscxCmdlet base uses a nested pipeline to run Test-Path when binding to LiteralPath or Path to verify any constraints. I don't know why this should be deadlocked, and I suspect it might be a bug [in powershell.]

I'll investigate some more to try to isolate the issue before pinging someone on the powershell team.

-Oisin

Developer
Jul 1, 2010 at 12:16 AM

OK, spent some time in WinDbg and yes, it's a deadlock but not a guaranteed one. There's a race condition between the eventing infrastructure and our cmdlet. I've contact the powershell team and I'll let you know [if I can] what's going on, and how to get around it.

Developer
Jul 1, 2010 at 1:30 AM

You would think so, but that’s the same problem I’m having with that Export-NamedElement cmdlet for PowerBoots in event handlers.

From: oisin

If you're in a PSCmdlet instance, you should assume you need a nested pipeline, right? The PSCmdlet wouldn't be executing if there was no pipeline...

-Oisin

On Tue, Jun 29, 2010 at 10:01 PM, Jaykul <notifications@codeplex.com> wrote:

From: Jaykul

This is one of those things where your cmdlet needs a pipeline, but it can't tell if it needs a Pipeline or a NestedPipeline

Developer
Jul 1, 2010 at 3:41 AM
Edited Jul 1, 2010 at 3:49 AM

I think the only way to avoid this is to use a separate runspace entirely [in our cmdlet.] I'm not sure there's any way to reliably avoid this externally.

Developer
Jul 1, 2010 at 4:58 AM

Well, you’re supposed to be able to check the state to determine if you need a nested pipeline or not, but that fails when you call it after creating a nested runspace, because they’re storing the state statically – major bug

From: oisin

I think the only way to avoid this is to use a separate runspace entirely, but this means you lose all access to previously in-scope items.

Developer
Jul 1, 2010 at 5:01 AM
That's an entirely separate bug. Not relevant here - the pipeline will always be nested, because it's running inside a cmdlet.

On Thu, Jul 1, 2010 at 12:58 AM, Jaykul <notifications@codeplex.com> wrote:

From: Jaykul

Well, you’re supposed to be able to check the state to determine if you need a nested pipeline or not, but that fails when you call it after creating a nested runspace, because they’re storing the state statically – major bug

From: oisin

I think the only way to avoid this is to use a separate runspace entirely, but this means you lose all access to previously in-scope items.

Read the full discussion online.

To add a post to this discussion, reply to this email (Pscx@discussions.codeplex.com)

To start a new discussion for this project, email Pscx@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com




--

---
404 signature missing
Jul 3, 2010 at 10:30 AM

So, what is solution? I can change the Exists method so it will not call call another cmdlet, but I believe the same approach (calling cmdlet inside the other) is used in many places across library, thus general solution will be much better.

Developer
Jul 4, 2010 at 6:21 PM

I can't see a solution right now for your situation other than not using an action handler. Try using Wait-Event in a loop instead and process in the main pipeline.

Jul 9, 2010 at 5:21 AM

Wouldn't something like creating a hardlink be better off if it was as close to nt api and as independent from powershell libs as possible? And in general to maybe kind of aim at having things as separable as possible at least for things that are low level operations by nature.

 

Developer
Aug 9, 2010 at 4:43 PM

Looks like a bug in powershell. You can vote on the issue I posted here:

https://connect.microsoft.com/PowerShell/feedback/details/584573/v2-race-condition-leading-to-possible-deadlock-in-creatednestedpipeline-when-used-in-event-handler

-Oisin