question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Tornado Next Tick Callback Issue

See original GitHub issue

Posted this to the Google Group a couple weeks ago but didn’t seem to get any activity there but wanted to bring this to attention:

Build is on bokeh 0.12.9, tornado version 4.5.2. Chrome browser.

I’ve been building an application to consume a UDP stream and add the data as it comes in to a bokeh plot. I can consume the UDP stream fine and most of the time the bokeh callbacks work to add the data but sometimes I get a long error message as follows:

2017-10-25 14:35:52,825 Exception in callback functools.partial(<function wrap.<locals>.null_wrapper at 0x000000ADC0CA3048>) Traceback (most recent call last): File “d:\afcbm\continuum\lib\site-packages\tornado\ioloop.py”, line 605, in _run_callback ret = callback() File “d:\afcbm\continuum\lib\site-packages\tornado\stack_context.py”, line 277, in null_wrapper return fn(*args, **kwargs) File “d:\afcbm\continuum\lib\site-packages\bokeh\util\tornado.py”, line 133, in wrapper self.remove_next_tick_callback(callback) File “d:\afcbm\continuum\lib\site-packages\bokeh\util\tornado.py”, line 160, in remove_next_tick_callback self._remove(callback, self._next_tick_callbacks) File “d:\afcbm\continuum\lib\site-packages\bokeh\util\tornado.py”, line 155, in _remove self._error_on_double_remove(callback, callbacks) File “d:\afcbm\continuum\lib\site-packages\bokeh\util\tornado.py”, line 116, in _error_on_double_remove raise ValueError(“Removing a callback twice (or after it’s already been run)”) ValueError: Removing a callback twice (or after it’s already been run)

Minimal Code example below:

import socket
import struct
import time
from bokeh.plotting import figure
from bokeh.layouts import column
from bokeh.models import ColumnDataSource
from bokeh.io import curdoc
from threading import Thread
from functools import partial
from tornado import gen

plot_column = column()

UDP_IP = "127.0.0.1" # 172.17.1.32
UDP_PORT = 29505

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP

sock.bind((UDP_IP, UDP_PORT))

doc = curdoc()

f = figure(plot_width=700, plot_height=200)
source = ColumnDataSource(data=dict(x=[], y=[]))
l = f.circle(x='x', y='y', source=source)
plot_column.children.insert(0, f)

@gen.coroutine
def update(x, val):
    source.stream(dict(x=[x], y=[val]))


def receive_loop():
    while True:
        data, addr = sock.recvfrom(1024) # buffer size
        val = struct.unpack('!i', data)[0]
        doc.add_next_tick_callback(partial(update, x=time.time(), val=val))


doc.add_root(plot_column)
thread = Thread(target=receive_loop)
thread.start()


Minimal code example for the client:

import socket
from random import random
import time
import struct

UDP_IP = "127.0.0.1" # 172.17.1.32
UDP_PORT = 29505

sock = socket.socket(socket.AF_INET,
                     socket.SOCK_DGRAM)
x = 0
while True:
    time.sleep(0.2)
    x += 1

    sock.sendto(struct.pack('!i', x), (UDP_IP, UDP_PORT))

Interestingly, I’ve been able to create a temporary workaround on my system by modifying the tornado.py file within bokeh by adding a time.sleep(.001) call at line 154 within the _remove method. With any amount of sleep in the process of removing the next tick callback the ValueError shown above doesn’t trigger. The error seems to show randomly on the system, with no real consistency of when it shows up within the stream of data.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:21 (14 by maintainers)

github_iconTop GitHub Comments

2reactions
aayla-securacommented, Mar 3, 2018

@bryevdv , the data I am reading in to common.hist comes from the network and should be the same for all sessions. It is not modified in any session, rather each session sets up a callback, waiting for common.hist to change and then makes a local copy of it. How else can more than one session read the same data from a TCP socket (well they can if using ZMQ PUB-SUB, but it would still require spawning a new thread every session, doesn’t scale well). I thought I can get away with spawning a thread by using unlocked callbacks and futures, but couldn’t get it to work (the server was still getting locked up). Anyway, this is not related to this issue, so I don’t want to span the thread, but I’m open to suggestions on a better way to implement live-plotting of streaming data from the network.

0reactions
bryevdvcommented, Mar 1, 2018

@aayla-secura i am glad you found a workaround, though just FYI I feel compelled to state that I would not consider any shared use of a Bokeh model between sessions as you are doing with the CDS in common.py to be a supported practice. Bokeh models should be created and exclusively confined to sessions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Issue with Tornado/Callbacks - Bokeh Discourse
I've been building an application to consume a UDP stream and add the data as it comes in to a bokeh plot. I...
Read more >
Streaming data with Bokeh and Panel periodic callbacks?
Hi everyone, I am trying to use the streaming capabilities of Bokeh in combination with the Panel library. More specifically, I am trying...
Read more >
What does the bokeh decorator @without_document_lock ...
It states: Normally Bokeh session callbacks recursively lock the document until all future work they initiate is complete. However, you may want ...
Read more >
What does process.nextTick(callback) actually do in Node.js?
It places the function you pass it on a call stack in the event loop for later processing. When the current execution context...
Read more >
Tornado Documentation
low-level components like the IOLoop that use callbacks. ... Coroutines will be discussed in depth in the next section of this guide.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found