Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closing/Disposing database throws Exception because of unfinished replicators #1020

Closed
thomai-d opened this issue Apr 26, 2018 · 9 comments
Closed
Assignees
Milestone

Comments

@thomai-d
Copy link

See the following code:
db

The Close() call throws an exception if a replicator has been started:

Couchbase.Lite.CouchbaseLiteException
  HResult=0x80131500
  Message=CouchbaseLiteException (LiteCoreDomain / 16): Cannot close the database. Please stop all of the replicators before closing the database..
  Source=Couchbase.Lite
  StackTrace:
   at Couchbase.Lite.Database.ThrowIfActiveItems()
   at Couchbase.Lite.Database.<Dispose>b__93_0()
   at Couchbase.Lite.Support.ThreadSafety.DoLocked(Action a)
   at Couchbase.Lite.Database.Dispose()
   at Couchbase.Lite.Database.Close()
   at TestApp.Service.CouchbaseDatabase..ctor() in ...\CouchbaseDatabase.cs:line 75

The replicator server is down and the following snippet is the only couchbase code that is executed in my testing application. The exception is raised on Android as well as on UWP.

Library Version

2.0.0.1

.NET Runtime

Xamarin Android v27.0.2
Microsoft.NETCore.UniversalWindowsPlatform v6.0.8

Operating System / Device Details

Android OS 6.01
Windows 10 Version 1709

Log Output

log-1524763742.zip

Expected behavior

this.db.Close() as well as this.db.Dispose() can be called without causing an exception.

Actual behavior

this.db.Close() as well as this.db.Dispose() throws an exception when a replicator is configured.

Steps To Reproduce

Execute given code:
this.db = new Database(DatabaseName);
var targetEndpoint = new URLEndpoint(new Uri("ws://192.168.0.11:4984/app"));
var replConfig = new ReplicatorConfiguration(this.db, targetEndpoint);
replConfig.Authenticator = new BasicAuthenticator("GUEST", "");
replConfig.Continuous = true;
this.replicator = new Replicator(replConfig);
this.replicator.Start();
this.replicator.Stop();
this.replicator.Dispose();
this.db.Close();

@borrrden
Copy link
Member

Calling Stop on the replicator is not a synchronous function so you must wait for the status to change to stopped. After that you can close the database. Let me know if that helps.

@thomai-d
Copy link
Author

thomai-d commented Apr 27, 2018

This won't help:

        this.db = new Database(DatabaseName);
        var targetEndpoint = new URLEndpoint(new Uri("ws://192.168.0.11:4984/app"));
        var replConfig = new ReplicatorConfiguration(this.db, targetEndpoint);
        replConfig.Authenticator = new BasicAuthenticator("GUEST", "");
        replConfig.Continuous = true;
        this.replicator = new Replicator(replConfig);
        Debug.WriteLine($"Before Start: {this.replicator.Status.Activity}");
        this.replicator.Start();
        Debug.WriteLine($"After Start: {this.replicator.Status.Activity}");
        this.replicator.Stop();
        Debug.WriteLine($"After Stop: {this.replicator.Status.Activity}");

        for (int n = 1; n <= 6; n++)
        {
            Thread.Sleep(10000);
            Debug.WriteLine($"After {n*10} seconds: {this.replicator.Status.Activity}");
        }

        this.replicator.Dispose();
        this.db.Close();

Will produce an output of:

Before Start: Stopped
After Start: Connecting
After Stop: Connecting
After 10 seconds: Busy
After 20 seconds: Busy
After 30 seconds: Busy
After 40 seconds: Busy
After 50 seconds: Busy
After 60 seconds: Busy
Exception thrown: 'Couchbase.Lite.CouchbaseLiteException' in Couchbase.Lite.dll
CouchbaseLiteException (LiteCoreDomain / 16): Cannot close the database. Please stop all of the replicators before closing the database..

Again, this behavior is only seen if the sync gateway is offline.
If the server is up, the state will change to "Stop" within a second and Disposing/Stopping is no problem.

@borrrden
Copy link
Member

For Xamarin this sounds like #1000 but I haven't heard of this happening on UWP yet.

@borrrden
Copy link
Member

FYI the fixes for that and other Xamarin replication issues are containing in the newest DB (2.1.0-db001)

@borrrden
Copy link
Member

borrrden commented May 8, 2018

Has the new DB cleared this up @thomai-d ?

@thomai-d
Copy link
Author

thomai-d commented May 8, 2018

2.1.0-db001 on UWP is still buggy.

Two cases:

  1. If I set the replicator to a nonexisting IP in the LAN, the replication state will hang in "Connecting" even if I call stop and wait for a long time. Calling database.Delete() will result in the same exception as above.

  2. If I set the replicator to a nonexisting IP in the Internet, the replication state will be "Stopped" but calling database.Delete() will also result in the exception.

@borrrden
Copy link
Member

borrrden commented May 9, 2018

I think we already have tests that cover the second case, but I will run something like that on my machine to see if I get the same result.

@borrrden
Copy link
Member

borrrden commented Jun 2, 2018

Sorry for the lack of response on this. I discovered a key problem today. Maybe this was supposed to be obvious but connecting a TcpClient to a non-existent IP address will not callback with an error. It will simply just not ever do anything and it's up to the caller to determine when too much time has passed and rule it "timed out". Because I assumed that there would be an error callback this means forever stuck in the connecting state (unless something suddenly becomes available on the other side I suppose).

Another thing is that it seems LiteCore doesn't obey stop until the initial connection either succeeded or failed. I have a fix in mind to help with this though.

Sandychuang8 pushed a commit that referenced this issue Jun 4, 2018
borrrden pushed a commit that referenced this issue Jun 4, 2018
Sandychuang8 pushed a commit that referenced this issue Jun 5, 2018
borrrden pushed a commit that referenced this issue Jun 6, 2018
…nnect (#1020) (PR #1033)

Inability to connect is not reported by TcpClient.  There needs to be logic to handle the case where the other side does not respond.
@borrrden
Copy link
Member

borrrden commented Jun 7, 2018

Forgot to include a message to close this, but it was closed with d3eb920

@borrrden borrrden closed this as completed Jun 7, 2018
@Sandychuang8 Sandychuang8 removed the ready label Jun 7, 2018
@borrrden borrrden added the bug label Aug 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants