GolosChain / golos

Socio-economic mediablockchain
https://developers.golos.io
Other
59 stars 36 forks source link

[0.17.0] [LOW_MEM] Exotic errors while reading multiple blocks at once #459

Closed bitphage closed 6 years ago

bitphage commented 6 years ago

While adopting golos-python to new API I launched library tests and one of them produces strange errors every time. This test is just performs multiple get_block calls in parallel.

You should be able to reproduce errors by running pipenv run py.test when I'll push adopted golos-python version.

_______________________________________________________________ test_ensured_block_ranges _______________________________________________________________

    def test_ensured_block_ranges():
        """ Post should load correctly if passed a dict or string identifier. """
        s = Steemd()
>       assert list(pluck('block_num', s.get_blocks_range(100, 200))) == list(
            range(100, 200))

tests/steem/test_steemd.py:8: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
steem/steemd.py:245: in get_blocks_range
    return self.get_blocks(list(range(start, end)))
steem/steemd.py:223: in get_blocks
    for block in self._get_blocks(missing):
steem/steemd.py:198: in _get_blocks
    for x in results:
steembase/http_client.py:293: in call_multi_with_futures
    yield future.result()
/usr/lib64/python3.6/concurrent/futures/_base.py:398: in result
    return self.__get_result()
/usr/lib64/python3.6/concurrent/futures/_base.py:357: in __get_result
    raise self._exception
/usr/lib64/python3.6/concurrent/futures/thread.py:55: in run
    result = self.fn(*self.args, **self.kwargs)
steembase/http_client.py:250: in call
    return_with_args=return_with_args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <steem.steemd.Steemd object at 0x7fef1fd7e630>, response = <urllib3.response.HTTPResponse object at 0x7fef1f7d3390>, args = (141,)
return_with_args = False

    def _return(self, response=None, args=None, return_with_args=None):
        return_with_args = return_with_args or self.return_with_args
        result = None

        if response:
            try:
                response_json = json.loads(response.data.decode('utf-8'))
            except Exception as e:
                extra = dict(response=response, request_args=args, err=e)
                logger.info('failed to load response', extra=extra)
                result = None
            else:
                if 'error' in response_json:
                    error = response_json['error']

                    if self.re_raise:
                        error_message = error.get(
                            'detail', response_json['error']['message'])
>                       raise RPCError(error_message)
E                       steembase.exceptions.RPCError: Assert Exception (10)
E                       b->block_num() == block_num: Wrong block was read from block log.
E                       rethrow
E                       rethrow

steembase/http_client.py:270: RPCError

Same test but exception is different:

>                       raise RPCError(error_message)
E                       steembase.exceptions.RPCError: basic_ios::clear: iostream error (13)
E                       rethrow basic_ios::clear: iostream error: 
E                       rethrow
>                       raise RPCError(error_message)
E                       steembase.exceptions.RPCError: basic_ios::clear: iostream error (13)
E                       basic_ios::clear: iostream error: error unpacking uint160_t
E                       Error unpacking field previous
E                       error unpacking golos::protocol::signed_block
E                       rethrow
E                       rethrow
>                       raise RPCError(error_message)
E                       steembase.exceptions.RPCError: basic_ios::clear: iostream error (13)
E                       basic_ios::clear: iostream error: 
E                       Error unpacking field timestamp
E                       error unpacking golos::protocol::signed_block
E                       rethrow
E                       rethrow
kotbegemot commented 6 years ago

https://github.com/GolosChain/golos/pull/460

afalaleev commented 6 years ago

The block_log has two file streams (data and index), and different methods for read and write. Each file stream has only ONE position for both type of operations, that is why it should be blocked before any operation, because it can be called from different threads: http://www.cplusplus.com/reference/fstream/fstream/