We're having a problem where the application pools restarts (and loses all sessions) when deleting a folder in a virtual directory. This is not ImageResizers fault, but ASP.NET. We cannot replicate the issue on a static web site.
I'm wondering if someone has resolved this issue? We're thinking about creating a separate web page just for ImageResizer and image content. Maybe there is a simpler way?
This solution did not work for us: http://www.aaronblake.co.uk/blog/2009/09/28/bug-fix-application-restarts-on-directory-delete-in-asp-net/
IIS and ASP.NET - both - have independent FileSystemWatchers. If you disable these, the problem should go away.
See http://imageresizing.net/docs/howto/avoid-network-limit for more information.
While the article above mentions the problem from the perspective of a latent network-based storage, the problem can appear in other ways - such as upon directory deletion.
I also suggest avoiding deleting folders on ASP.NET websites; it's a painful goal, and likely to fail due to read locks. Goodnes, folder deletion rarely works on windows — even when it's not part of a web site being actively served to clients.
It seems to be possible to use IIS application instead of Virtual directory, and use a different application pool for the image archive. I tried, and the problem was solved... this appool restarted instead, which didn't affect the web pool. Great success!
However, I don't think we will be doing this either. It seems as a IIS application needs it's own bin folder. I had to copy the image resizer DLLs here. I also had to write another global.asax for auto 404 images in Application_Start. It works... I just don't want the image directory to have a lot of code in it. It is synced from a third party.
Related
I have the following scenario:
I publish a page which contains multiple binaries which is then received by an HTTP Receiver and Deployed using an in-process Deployer all hosted in IIS in a dedicated application pool running as the Local Service user.
The Page is stored in the Broker Database, and the binaries are published to the local file system using a path like "D:\Binaries\Preview".
The preview folder is shared to a domain user as a read only share at something like \machinename\PreviewBinaries so that the binaries can be displayed using the web application.
Nine time out of ten everything works fine, but occasionally publishing fails, and it seems to be because the binaries can not be overwritten due to them being locked by another process. I have used ProcessMon and other tools to try and establish what might be locking these files (to no avail). Sometimes I can manually delete the images, and then publishing works again. If I restart IIS on the server I can always delete the files and publish.
Does anyone have any suggestions on what processes could be locking these images? Has anyone seen this issue before? Could there be any issues that I am publishing to a share? Or could SiteEdit 2009 possibly be locking these files as it only seems to occur on our preview server and live (no SiteEdit) seems fine.
Thanks in advance
If you're on Windows 2008, you can try and delete the file from disk. It will then tell you what process has locked the file. But given that restarting IIS unlocks the file, it seems quite likely that it is IIS that keeps a lock on them.
I don't see how SiteEdit 2009 could cause a lock on these files. Given that you can have your preview server on another box, SiteEdit only talks to that server through HTTP. It never accesses the files on the preview server directly and not even through a CD API. Just regular requests to your web server, just like a visitor would.
Again, not a direct answer but I wanted to share this anyway:
I've seen a similar situation where I published Pages to the Broker Database and Binaries to the file system. When I changed the Identity of the Application Pool to Network Service this problem disappeared, and I haven't looked into it further.
OK, well it seems the offending code was in the Presentation Framework we are using. The framework used Response.TransmitFile(binaryPath) to asynchronously transmit the binaries to the clients. It seems that this puts a temporary lock handle on the binaries (even when they are on a read only share).
We have removed this line of code, and modified the application to server binaries in another way (we now rewrite the path so that IIS can transmit the files directly). This seems to have solved the issue, and improved site performance.
Thanks for all your suggestions, it helped me rule out all the things that were not causing the issue, so I was able to find the root cause.
Are there any Anti-virus or indexing services running. These tend to take very short-lived locks at just the moment you don't want them to. Particularly with Anti-virus, this is typically just as one process relinquishes its lock and just before your other process tries to take one. If this is the issue, then setting up some exclusion directories should help.
I see you have used Process Monitor, but have you tried Sysinternals Process Explorer? "Find->Find Handle or Dll" is pretty useful for this kind of thing. Or if you prefer a command line tool, Sysinternals aslo make handle.exe, which dumps everything out for you.
We have an asp.net web site that is deployed on several IIS servers. The site is compile-on-demand as opposed to a pre-compiled web application.
Normally deployments go fine but every now and again we get a 401 for one of the deployed pages on one of the servers. There is nothing special about which page or which server apart from the fact that it's generally the higher traffic pages that it happens to.
The only way to rectify this is to deploy the same page again.
The ACLs look fine on the files themselves so the thought is that there is a file locking issue in the Temporary ASP.NET Files folder when the specific page is re-compiled.
Has anyone seen this before or have any suggestions how to avoid this?
Note: This only seems to have happened since we moved to .net 4.0
As far as I can tell we are getting a 401.3 Denied by resource ACL http://support.microsoft.com/kb/907273
But I have not been able to confirm this.
Those kinds of locks have always been a problem with live site deployment. The reason it's hard to replicate is because you are mid-request when copying/compiling on the server, and this ends up confusing IIS.
We operate a Blue/Green deployment strategy on a 4 tier architecture which has a web site over 4 servers at the top tier. Due to the complexity the architecture introduced for deployments, we needed a way to deploy without disturbing any traffic to the "live" site. Following Fowler's advice, but not quite in the same way, we came up with a solution that means we have 2 sites on each server (a blue and a green, or in our case site A and site B). The live site has the appropriate host header, and once we have deployed and tested to the non-live site, we then flip the headers of the 2 sites so that what was once live is now the non-live site, and vice-versa. The effect is, a robust deployment that can be done in hours and with the highest level of confidence.
This of course complicates your configuration and deployment slightly, but it's worth the effort. I guess it kind of goes without saying that you want to script both the deployment, and the host header swapping.
When i deploy to a server i bring the site down for a minute (or however long the deployment takes) - it may be down anyway during this time as pages are recompiled so it is not too much of a hit. You can do this by creating a file in the root of the app called app_offline.aspx (it needs at least 512 characters in length) once that file is created you can then copy the resources ot the folder knowing there will not be any locking issues. then when the copy is complete remove the app_offline file.
For those that want to achieve a .net website deployment without these issues, one option is to copy the new website files into a new folder first ( not the active website). Then you just change IIS to point to the new folder after all copying is complete.
This can be done in a single server environment for those of us on more limited resources without multiple servers per website.
At my work we write power shell scripts to deploy websites. The powers shell script creates a new directory with a time stamp, copies the new deployment there, then tells IIS to point the website to the new directory (leaving the old directories "orphaned" but still there).
If we really messed something up, we can simply revert by pointing IIS back at the previous date stamp directory. Otherwise if everything tests ok, we can delete the old folder.
This technique works well because you are never writing over a file while it is in use. However it still results in zero downtime. The only effect you will see is the normal .net "warm up" that occurs anytime you change the code behinds or assemblies.
I had several answers suggesting a new environment to deploy. This is something we have been considering for the long term but it's hard to justify the extra work when we regularly deploy only one or two files without a problem. I was really more interested in finding out what is actually happening and why.
In terms of a workaround, and this might sound obvious after the fact, a simple app_pool recycle solves the permissions issue and is much easier than testing for the issue and redeploying the file until the problem goes away.
Can we depend on the current working directory in ASP.NET code-behinds? Or, in other words, can we use relative paths, and be sure that they'll work?
If, in one page on a website, I set the current working directory to something specific, will it still be the same the next time another page on the website is loaded? When the same page on the website is loaded?
If I set the current working directory to something specific, in Page_Load(), can I be sure that it will still be the same by the time Page_PreRender() is called? Or could another page on the same website change it on me, in between? Could a page on a different website in the same application pool change it on me? A page in a different website in a different app pool?
In other words, what is the scope of the current working directory, in IIS? Is it specific to a page? Is it specific to a web site? Or is it shared among all pages in an app pool?
Where, among page, website, app pool, and server, are the boundaries that isolate different values of current working directory?
AppDomain.CurrentDomain.RelativeSearchPath will give you the physical path to the bin folder
Environment.CurrentDirectory is a simple wrapper around the GetCurrentDirectory and SetCurrentDirectory winapi functions. Indeed, trying to set the directory requires UnmanagedCode permissions. Whenever a function prevents your site from running in partial trust, you are right to be wary of depending on it. :)
From the SetCurrentDirectory documentation:
Changes the current directory for the current process.
The best explanation I can find that covers the relationship between the w3wp.exe process and an ASP.NET site is this answer. Any other page within your site could potentially change your page's current working directory. Any pages on any other site under the same application pool could potentially change your page's current working directory. These outside changes to the current working directory could happen at any time during your page's execution. On the other hand, a page on a site under a different application pool will not change your page's current working directory. The reason I say "could potentially" is that it gets even more complicated if you consider web garden scenarios, where there can be more than one process for a single ASP.NET site.
Now consider that SetCurrentDirectory is not thread safe:
Multithreaded applications and shared
library code should not use the
SetCurrentDirectory function and
should avoid using relative path
names. The current directory state
written by the SetCurrentDirectory
function is stored as a global
variable in each process, therefore
multithreaded applications cannot
reliably use this value without
possible data corruption from other
threads that may also be reading or
setting this value. This limitation
also applies to the
GetCurrentDirectory and
GetFullPathName functions. The
exception being when the application
is guaranteed to be running in a
single thread, for example parsing
file names from the command line
argument string in the main thread
prior to creating any additional
threads. Using relative path names in
multithreaded applications or shared
library code can yield unpredictable
results and is not supported.
Chances are that you don't want to depend on the current working directory. Having said that, given how foolish it is to rely on the current working directory, you can be reasonably certain that no other code will be touching it. :) A quick peek with Reflector shows that no .NET framework code changes it. A few functions do check it though, so watch out for those. If you control the deployment environment, you can ensure that your site runs in its own application pool. With proper synchronization technique, you should then be able to safely update the current working directory. I wouldn't consider it anything other than a hack though.
Links should be created relative to the site root using the tilde (~) operator:
Some Page
Within a server, an application pool completely isolates your site so that if some other site crashes on the same server, it won't bring down your site with it. IIS is pretty much site-specific with the added isolation benefits of app pools. I can see no practical use in trying to change a link on one page from the code-behind in another (or maybe I don't quite understand the question).
Here's a summary of the IIS architecture:
http://learn.iis.net/page.aspx/243/aspnet-integration-with-iis-7/
I am having an ongoing situation where when I try to upload files via FTP that I get an error that the DLL is locked and currently cannot be overwritten. This is only DLLs that this is happeneing to and normal files (aspx, ascx, css etc) can be overwritten fine.
Our Setup
We have 2 webservers that are kept in sync via DFS which is managed from a separate server.
They all belong to the same domain.
They all do internal transfers on 1GB ethernet cards on a private network.
Our Problem
We develop in VS2010 and build the site we are working on, when it gets to a level where it needs to be checked on the server then its hit and miss whether we can overwrite the DLL's in the BIN folder. I only started experiencing this issue when we migrated from our old, unreliable sync tool to the super Windows 2008 DFS tool. Its a good tool and works well but this is the only thing I can think thats causing this issue.
To actually overwrite the file I need to take down all the sites that are using this base level code which then releases the lock on the DLL and I can upload it.
I come today in desperation, I am fed up and bored of having to take sites down every so often just so I can upload a DLL.
It is my understanding that ASP.Net caches the DLLs into a temporary folder, so god knows why the lock remains on the DLL itself in the BIN folder.
The weird thing is, this does not always happen, it can go for weeks and not do it. Or like recently, its around every day I have to take the IIS sites down so I can upload.
As of writing this, I cannot upload to FTP even though I have taken the sites down.
Could anyone please shed any light on this so I can actually just get on with my work rather than messing with this every ten mins. It's bad enough that VS2010 is so unstable and visual source safe only checks in what it wants without this being an issue as well!
Trying using UnLocker to free the handles.
Basically I want the effect that would occur if I were to edit the web.config file. The application basically completely unloads itself and starts again, thus re-firing Application_Start and also ditching any dynamically created Types created by the now-defunct AppDomain.
EDIT
I need to do this in my C# code inside my web application. I know it can be done; I did it ages ago but have since lost the code and forgotten how I did it.
For full trust you can use HttpRuntime.UnloadAppDomain(). If you aren't running in full trust you can modify the last write time on the web.config file. Rick Strahl has wrapped these two approaches up in a nice class.
You can "touch" the web.config file (i.e. rewrite it to disk unchanged), or any file in the bin directory to recycle the application. Of course this means the identity under which your application is running needs appropriate permissions.
Lately I seem to be answering my own questions a lot :P
Here we go:
HttpRuntime.UnloadAppDomain();
If all the options above fail, you can also create an endless recursive function as a final resort. The resulting stackoverflow exception will force a reload of the application. (don't do this when you have the visual studio debugger attached)
In IIS you can recycle the worker processes. You don't need to restart IIS.
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/24e3c22e-79a9-4f07-a407-dbd0e7f35432.mspx?mfr=true
If you have created a separate application pool for your application, you can reset the Application Pool.
In general, it's always a good idea to have separate app pool's for each application.