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

Thin and ActiveRecord's ConnectionManagement do not work together #307

Closed
mrrusof opened this Issue Apr 20, 2016 · 12 comments

Comments

Projects
None yet
3 participants
@mrrusof

mrrusof commented Apr 20, 2016

I was playing around with Sinatra and ActiveRecord when I found that a connections are not reused automatically by this simple API.

#!/usr/bin/env ruby                                                                                  

require 'sinatra'
require 'active_record'

ActiveRecord::Base.establish_connection(
adapter:  'sqlite3',
database: 'newsletter.db'
)

ActiveRecord::Schema.define do
  create_table :subscribers do |t|
    t.string :email
    t.timestamps
  end
end

class Subscriber < ActiveRecord::Base
  validates :email, presence: true
end

class Newsletter < Sinatra::Base

  set :server, :thin
  use ActiveRecord::ConnectionAdapters::ConnectionManagement

  get '/subscribers/:email' do
    s = Subscriber.find_by_email(params[:email])
    if s == nil
      status 404
    else
      content_type 'application/json'
      s.to_json
    end
  end

  post '/subscribers/:email' do
    Subscriber.create(email: params[:email])
  end

end

Newsletter.run!

The API returns either a subscriber or a 404 the first 5 times I GET a subscriber. The 6th time I get a timeout. After each of the first 5 GETs, there is one more read+write file descriptor open for newsletter.db. I would expect there to be only one all the time.

The reason for the timeout is that Thin starts processing each request in a thread and finishes processing the request in another thread. ConnectionManagement only returns to the pool those connections that are active for the current thread and Thin applies ConnectionManagement in the second thread instead of the first.

Is it responsibility of Thin to process each request in a single thread or is it responsibility of ConnectionManagement to close active connections for a given thread instead of the current thread?

@macournoyer

This comment has been minimized.

Show comment
Hide comment
@macournoyer

macournoyer Apr 22, 2016

Owner

Thin doesn't use threads by default. Unless you specify --threaded option, did you?

If not, everything runs in a single thread and there is no need to use a connection pool w/ AR.

Owner

macournoyer commented Apr 22, 2016

Thin doesn't use threads by default. Unless you specify --threaded option, did you?

If not, everything runs in a single thread and there is no need to use a connection pool w/ AR.

@mrrusof

This comment has been minimized.

Show comment
Hide comment
@mrrusof

mrrusof Apr 22, 2016

I did not specify option --threaded. I ran the example API like so ./example.rb. I know that when I run my example Thin starts processing a request in one thread and finishes in another because I did the following modification to ConnectionManagement.

    class ConnectionManagement
      def initialize(app)
        @app = app
      end

      def call(env)
        testing = env['rack.test']

        puts '*******************************************************************************'
        puts 'ConnectionManagement.call'
        puts Kernel.caller
        puts "Thread.current.object_id = #{Thread.current.object_id}"
        puts '*******************************************************************************'
        response = @app.call(env)
        response[2] = ::Rack::BodyProxy.new(response[2]) do
          puts '*******************************************************************************'
          puts '::Rack::BodyProxy.new(response[2]) do'
          puts Kernel.caller
          puts "Thread.current.object_id = #{Thread.current.object_id}"
          puts '*******************************************************************************'
          ActiveRecord::Base.clear_active_connections! unless testing
        end

        response
      rescue Exception
        ActiveRecord::Base.clear_active_connections! unless testing
        raise
      end
    end

For the modified ConnectionManagement, I get the following output after I GET.

ruslan$ ./example.rb
== Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from Thin
Thin web server (v1.6.4 codename Gob Bluth)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
*******************************************************************************
ConnectionManagement.call
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/path_traversal.rb:16:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/nulllogger.rb:9:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/show_exceptions.rb:25:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:182:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:2013:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:in `block in call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1787:in `synchronize'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:86:in `block in pre_process'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:84:in `catch'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:84:in `pre_process'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:1076:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:1076:in `block in spawn_threadpool'
Thread.current.object_id = 70307221466660
*******************************************************************************
*******************************************************************************
::Rack::BodyProxy.new(response[2]) do
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/body_proxy.rb:18:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/body_proxy.rb:18:in `close'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/response.rb:83:in `close'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:142:in `close_request_response'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:154:in `terminate_request'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:130:in `post_process'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:969:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:969:in `run_deferred_callbacks'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:194:in `run_machine'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:194:in `run'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/backends/base.rb:73:in `start'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/server.rb:162:in `start'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/handler/thin.rb:19:in `run'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1506:in `start_server'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1444:in `run!'
./example.rb:37:in `<main>'
Thread.current.object_id = 70307218276860
*******************************************************************************

When ActiveRecord::Base.clear_active_connections! is called from thread 70307218276860, the connection pool cannot find any active (aka reserved) connections for the thread because that thread does not have any. The connection that ActiveRecord made for the GET request was made from thread 70307221466660.

It may be true that Thin does not use threads by default. However, it appears that when it does, ConnectionManagement cannot do its job. I'm trying to understand if this is considered a problem by anyone (Thin, ActiveRecord, Sinatra-ActiveRecord).

mrrusof commented Apr 22, 2016

I did not specify option --threaded. I ran the example API like so ./example.rb. I know that when I run my example Thin starts processing a request in one thread and finishes in another because I did the following modification to ConnectionManagement.

    class ConnectionManagement
      def initialize(app)
        @app = app
      end

      def call(env)
        testing = env['rack.test']

        puts '*******************************************************************************'
        puts 'ConnectionManagement.call'
        puts Kernel.caller
        puts "Thread.current.object_id = #{Thread.current.object_id}"
        puts '*******************************************************************************'
        response = @app.call(env)
        response[2] = ::Rack::BodyProxy.new(response[2]) do
          puts '*******************************************************************************'
          puts '::Rack::BodyProxy.new(response[2]) do'
          puts Kernel.caller
          puts "Thread.current.object_id = #{Thread.current.object_id}"
          puts '*******************************************************************************'
          ActiveRecord::Base.clear_active_connections! unless testing
        end

        response
      rescue Exception
        ActiveRecord::Base.clear_active_connections! unless testing
        raise
      end
    end

For the modified ConnectionManagement, I get the following output after I GET.

ruslan$ ./example.rb
== Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from Thin
Thin web server (v1.6.4 codename Gob Bluth)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
*******************************************************************************
ConnectionManagement.call
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/path_traversal.rb:16:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/nulllogger.rb:9:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/head.rb:13:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/show_exceptions.rb:25:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:182:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:2013:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:in `block in call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1787:in `synchronize'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:86:in `block in pre_process'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:84:in `catch'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:84:in `pre_process'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:1076:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:1076:in `block in spawn_threadpool'
Thread.current.object_id = 70307221466660
*******************************************************************************
*******************************************************************************
::Rack::BodyProxy.new(response[2]) do
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/body_proxy.rb:18:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/body_proxy.rb:18:in `close'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/response.rb:83:in `close'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:142:in `close_request_response'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:154:in `terminate_request'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/connection.rb:130:in `post_process'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:969:in `call'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:969:in `run_deferred_callbacks'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:194:in `run_machine'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:194:in `run'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/backends/base.rb:73:in `start'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/thin-1.6.4/lib/thin/server.rb:162:in `start'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/rack-1.6.4/lib/rack/handler/thin.rb:19:in `run'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1506:in `start_server'
/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/sinatra-1.4.7/lib/sinatra/base.rb:1444:in `run!'
./example.rb:37:in `<main>'
Thread.current.object_id = 70307218276860
*******************************************************************************

When ActiveRecord::Base.clear_active_connections! is called from thread 70307218276860, the connection pool cannot find any active (aka reserved) connections for the thread because that thread does not have any. The connection that ActiveRecord made for the GET request was made from thread 70307221466660.

It may be true that Thin does not use threads by default. However, it appears that when it does, ConnectionManagement cannot do its job. I'm trying to understand if this is considered a problem by anyone (Thin, ActiveRecord, Sinatra-ActiveRecord).

@macournoyer

This comment has been minimized.

Show comment
Hide comment
@macournoyer

macournoyer Apr 22, 2016

Owner

What is weird is that this line indicate the Thin was started in threaded mode:

/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:1076:in `block in spawn_threadpool'

EDIT: I just noticed that Sinatra now default to threaded mode w/ Thin. Thin uses a thread pool in that case (same w/ Puma). Will investigate...

In the meantime you can disable threaded mode w/:

set :threaded, false
Owner

macournoyer commented Apr 22, 2016

What is weird is that this line indicate the Thin was started in threaded mode:

/Users/ruslan/.rvm/gems/ruby-2.2.1/gems/eventmachine-1.2.0.1/lib/eventmachine.rb:1076:in `block in spawn_threadpool'

EDIT: I just noticed that Sinatra now default to threaded mode w/ Thin. Thin uses a thread pool in that case (same w/ Puma). Will investigate...

In the meantime you can disable threaded mode w/:

set :threaded, false
@mrrusof

This comment has been minimized.

Show comment
Hide comment
@mrrusof

mrrusof Apr 22, 2016

I see. I don't want to disable threaded mode. I want to release connections automatically by means of ConnectionManagement. What I am hearing is that Thin is not responsible for processing each request from beginning to end in the same thread when it runs in threaded mode. If that is the case, I am ok with that.

Here is what I will do in the meantime instead of disabling threaded mode.

...
class Newsletter < Sinatra::Base

  set :server, :thin

  after do
     ActiveRecord::Base.clear_active_connections!
  end

  get '/subscribers/:email' do
    s = Subscriber.find_by_email(params[:email])
...

EDIT:

Thank you for taking time to reply to this issue!

mrrusof commented Apr 22, 2016

I see. I don't want to disable threaded mode. I want to release connections automatically by means of ConnectionManagement. What I am hearing is that Thin is not responsible for processing each request from beginning to end in the same thread when it runs in threaded mode. If that is the case, I am ok with that.

Here is what I will do in the meantime instead of disabling threaded mode.

...
class Newsletter < Sinatra::Base

  set :server, :thin

  after do
     ActiveRecord::Base.clear_active_connections!
  end

  get '/subscribers/:email' do
    s = Subscriber.find_by_email(params[:email])
...

EDIT:

Thank you for taking time to reply to this issue!

@QuakePhil

This comment has been minimized.

Show comment
Hide comment
@QuakePhil

QuakePhil Apr 29, 2016

@macournoyer I'm interested in resolving this also. For now, I have disabled threading, at the expense of significant performance...

@mrrusof the "after do clear active connections" fix works for me only 99% of the time, other 1% I still get a core dump (sometimes pages of output, sometimes just 2 lines)

would like to know a general solution for this

QuakePhil commented Apr 29, 2016

@macournoyer I'm interested in resolving this also. For now, I have disabled threading, at the expense of significant performance...

@mrrusof the "after do clear active connections" fix works for me only 99% of the time, other 1% I still get a core dump (sometimes pages of output, sometimes just 2 lines)

would like to know a general solution for this

@mrrusof

This comment has been minimized.

Show comment
Hide comment
@mrrusof

mrrusof Apr 29, 2016

@QuakePhil I did not expect anybody to run into a problem by applying my solution. Could you help me understand your problem by providing me a sample stack trace? You could mail it to my username at gmail.com.

mrrusof commented Apr 29, 2016

@QuakePhil I did not expect anybody to run into a problem by applying my solution. Could you help me understand your problem by providing me a sample stack trace? You could mail it to my username at gmail.com.

@macournoyer

This comment has been minimized.

Show comment
Hide comment
@macournoyer

macournoyer May 13, 2016

Owner

Sorry for the delay.

@mrrusof I did not manage to reproduce w/ the code in your original comment. My guess is that a middleware is not wrapping the response body properly, this preventing the Rack::BodyProxy#close from being called. Can you try this code: it should output "Body closed" each time you GET /.

require 'sinatra'

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    response = @app.call(env)
    response[2] = ::Rack::BodyProxy.new(response[2]) do
      puts "Body closed"
    end

    response
  end
end

class App < Sinatra::Base

  set :server, :thin
  use Middleware

  get '/' do
    'ok'
  end
end

App.run!

@QuakePhil @mrrusof didn't experience any coredump AFAICT. If you get a backtrace in that coredump, can you paste it?

Owner

macournoyer commented May 13, 2016

Sorry for the delay.

@mrrusof I did not manage to reproduce w/ the code in your original comment. My guess is that a middleware is not wrapping the response body properly, this preventing the Rack::BodyProxy#close from being called. Can you try this code: it should output "Body closed" each time you GET /.

require 'sinatra'

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    response = @app.call(env)
    response[2] = ::Rack::BodyProxy.new(response[2]) do
      puts "Body closed"
    end

    response
  end
end

class App < Sinatra::Base

  set :server, :thin
  use Middleware

  get '/' do
    'ok'
  end
end

App.run!

@QuakePhil @mrrusof didn't experience any coredump AFAICT. If you get a backtrace in that coredump, can you paste it?

@mrrusof

This comment has been minimized.

Show comment
Hide comment
@mrrusof

mrrusof May 14, 2016

@macournoyer I ran your example and I agree that after processing each GET request you and I will find "Body closed" in our consoles. Unfortunately, the example does not model the conditions for the bug because the call puts "Body closed" prints its argument regardless of the thread where it executes. Consider the code of middleware ConnectionManagement in connection_pool.rb of ActiveRecord 4.2.6.

645 class ConnectionManagement
646   def initialize(app)
647     @app = app
648   end
649
650   def call(env)
651     testing = env['rack.test']
652
653     response = @app.call(env)
654     response[2] = ::Rack::BodyProxy.new(response[2]) do
655       ActiveRecord::Base.clear_active_connections! unless testing
656     end
657
658     response
659   rescue Exception
660     ActiveRecord::Base.clear_active_connections! unless testing
661     raise
662   end
663 end

The call in line 655 is sensitive to the thread where it executes because it clears connections for the current thread. Given that Thin executes lines 653 and 655 in different threads, line 655 does not clear the connection created in line 653. I give more details in this blog post.

2016.05.13.11:43 CDT EDIT: Corrected URL of blog post.

mrrusof commented May 14, 2016

@macournoyer I ran your example and I agree that after processing each GET request you and I will find "Body closed" in our consoles. Unfortunately, the example does not model the conditions for the bug because the call puts "Body closed" prints its argument regardless of the thread where it executes. Consider the code of middleware ConnectionManagement in connection_pool.rb of ActiveRecord 4.2.6.

645 class ConnectionManagement
646   def initialize(app)
647     @app = app
648   end
649
650   def call(env)
651     testing = env['rack.test']
652
653     response = @app.call(env)
654     response[2] = ::Rack::BodyProxy.new(response[2]) do
655       ActiveRecord::Base.clear_active_connections! unless testing
656     end
657
658     response
659   rescue Exception
660     ActiveRecord::Base.clear_active_connections! unless testing
661     raise
662   end
663 end

The call in line 655 is sensitive to the thread where it executes because it clears connections for the current thread. Given that Thin executes lines 653 and 655 in different threads, line 655 does not clear the connection created in line 653. I give more details in this blog post.

2016.05.13.11:43 CDT EDIT: Corrected URL of blog post.

@macournoyer

This comment has been minimized.

Show comment
Hide comment
@macournoyer

macournoyer May 15, 2016

Owner

Can you five #312 a try. Pretty sure that fixes it. All the post processing was done in the main thread but the app was called in a separate thread.

Owner

macournoyer commented May 15, 2016

Can you five #312 a try. Pretty sure that fixes it. All the post processing was done in the main thread but the app was called in a separate thread.

@macournoyer macournoyer closed this in #312 May 18, 2016

@mrrusof

This comment has been minimized.

Show comment
Hide comment
@mrrusof

mrrusof May 18, 2016

@macournoyer: #312 works like a breeze, thank you! When will you release the fix?

mrrusof commented May 18, 2016

@macournoyer: #312 works like a breeze, thank you! When will you release the fix?

@mrrusof

This comment has been minimized.

Show comment
Hide comment
@mrrusof

mrrusof May 31, 2016

Fix is released in version 1.7.0.

mrrusof commented May 31, 2016

Fix is released in version 1.7.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment