U4-6811 - Couldnt delete preview set exception

Created by Martin Griffiths 09 Jul 2015, 10:47:49 Updated by Jeroen Breuer 06 Apr 2017, 09:49:09

Subtask of: U4-9609

2015-07-09 11:39:04,343 [38] ERROR umbraco.presentation.preview.PreviewContent [(null)] - [T38/D2] Couldn't delete preview set: 19_ea0f504e-9ebf-4036-9892-d829bfdd7a3e.config - User 19

System.IO.IOException: The process cannot access the file '19_ea0f504e-9ebf-4036-9892-d829bfdd7a3e.config' because it is being used by another process. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileInfo.Delete() at umbraco.presentation.preview.PreviewContent.DeletePreviewFile(Int32 userId, FileInfo file)

Appearing regularly in my logs and preventing some users from seeing a preview, preview scrrappears blank.

2 Attachments

Comments

Martin Griffiths 29 Jul 2015, 13:01:06

This error is still happening in 7.2.8. Most of the time previews seem to continue to work, but we've had a few support calls from users saying the preview is blank.


scott chidester 04 Sep 2015, 16:52:53

I am also seeing this error in the log files and users are experiencing a blank preview page sometimes. (Using 7.2.8). Any ideas on a fix?


Stephan 09 Sep 2015, 08:13:14

Any chance you have a complete stack trace, ie with whatever calls DeletePreviewFile?

Also found that code in PreviewContent.cs:

// also delete any files accessed more than one hour ago foreach (FileInfo file in dir.GetFiles("*.config")) { if ((DateTime.Now - file.LastAccessTime).TotalMinutes > 1) DeletePreviewFile(userId, file); }

Note that the comment says "more than one hour ago" but the comparison is on TotalMinutes, meaning we try to delete file that have not been used over the past minute... which might be too short. And, in any case, failing to delete a preview set is not really an immediate issue -- we just want to make sure we're not keeping files around for ages) so maybe we should not throw immediately.


Stephan 14 Sep 2015, 10:42:11

Edit: in fact, we are reporting the error but ''not'' throwing so that's not really the issue. Pushed af2dbc7cd9269a3a5b00a625380626ecbb6a850b so we delete files older than 10mins. Not sure yet why that error would break preview, though...


Simon Dingley 23 Jan 2017, 16:36:39

I am seeing this regularly in a 7.5.3 load-balanced site.


Bradley Kronson 08 Mar 2017, 10:50:46

I don't know if this is related, but I either see the error above or the following stack trace when previews go wrong

The process cannot access the file 'C:\Domains\xyzhttp://xyz\App_Data\preview\5_1bab88e5-b2e6-4dc0-8c06-89f85514e797.config' because it is being used by another process.

EXCEPTION DETAILS: System.IO.IOException: The process cannot access the file 'C:\Domains\xyzhttp://xyz\App_Data\preview\5_1bab88e5-b2e6-4dc0-8c06-89f85514e797.config' because it is being used by another process. STACKTRACE:

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share) at System.Xml.XmlDocument.Save(String filename) at Umbraco.Web.Editors.ContentController.UpdatePreviewContext(Int32 contentId) at Umbraco.Web.Editors.ContentController.PostSave(ContentItemSave contentItem) at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c_DisplayClass10.b_9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary2 arguments, CancellationToken cancellationToken) — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()


Jeroen Breuer 16 Mar 2017, 12:05:08

Could this also cause the "Save and publish" to be very slow? We're also seeing this error on a load balance environment. I did some tests by pressing "Save and publish" on the same node multiple times. On average it only takes about 1 second (see postsave1.png). But after a few publishes it can suddenly take up to 4 minutes (see postsave2.png). In the log I get the same exception mentioned in this issue:

2017-03-16 12:52:25,474 [7] ERROR umbraco.presentation.preview.PreviewContent - Couldn't delete preview set: 0_ac57932b-f710-4662-8819-faf0f240c1d3.config - User 0 System.IO.IOException: The process cannot access the file '0_ac57932b-f710-4662-8819-faf0f240c1d3.config' because it is being used by another process. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileInfo.Delete() at umbraco.presentation.preview.PreviewContent.DeletePreviewFile(Int32 userId, FileInfo file)


Jeroen Breuer 16 Mar 2017, 13:17:22

In the PostSave method the UpdatePreviewContext method is called which eventually tries to call CleanPreviewDirectory. So it seems related to why "Save and publish" can take a long time.


Stephan 22 Mar 2017, 11:13:59

@jbreuer can you confirm that the "Save and Publish" taking a long time is related to previewing? Ie that previewing causes "Save and Publish" to take a long time?

Early findings: when previewing, "Save and Publish" needs to rebuild the preview cache, which essentially means cloning the master Xml cache, then updating it with draft content loaded from the database, then saving it again. This is highly expensive.

Now about the "couldn't delete preview set"... each of these files are named eg "123_....config" where 123 is the user ID, and since in theory 1 user is doing 1 thing at a time, it's hard to see why there would be conflicts.

Unless, of course, the same identifier is used by more that 1 person at a time. And since we try to delete all "123_*.config" files, there ''could'' be conflicts.


Stephan 22 Mar 2017, 11:18:55

PR https://github.com/umbraco/Umbraco-CMS/pull/1812

what it does: stop deleting user's preview files immediately, in case user is logged in multiple times. swallow exceptions in case file is locked somehow.

review: code review, guess it's hard to reproduce anyways.

if we have another nasty issue with preview, then we'll start seeing exceptions when saving the file, but I doubt it. also, this does not address the performance issue, which would require a heavy refactoring of preview.


Shannon Deminick 23 Mar 2017, 00:07:10

@zpqrtbnk I've changed this slightly in this rev: 3b22c0cdd7774e6a6d99098b55ca49330a3dde56 we should be catching the exeception type we are expecting not just the generic exception type. So we'll ignore IOException but log for anything else.


Jeroen Breuer 06 Apr 2017, 09:49:09

I've upgrade to Umbraco 7.5.12, but the PostSave issue is still there. Created a topic for it: https://our.umbraco.org/forum/using-umbraco-and-getting-started/85046-postsave-action-can-take-minutes


Priority: Task - Pri 1

Type: Bug

State: Fixed

Assignee:

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted:

Affected versions: 7.5.3, 7.5.6

Due in version: 7.5.12

Sprint: Sprint 55

Story Points: 3

Cycle: