Skip to content

Concurrency issues in polybar (list of bugs) #1732

@Lomadriel

Description

@Lomadriel

This issue is a list of concurrency issues that must find solution:

  1. Issue in timer_module:
    1.1.
    https://github.com/jaagr/polybar/blob/7414e9800879cc3692af5ca217fdb18978ba8b4a/include/modules/meta/timer_module.hpp#L33
    Here there is a call to a virtual method however when the class is destroyed by the controller
    https://github.com/jaagr/polybar/blob/7414e9800879cc3692af5ca217fdb18978ba8b4a/src/components/controller.cpp#L140-L149
    the thread still run and this may leads to a non desired behavior since it is quite dangerous to call virtual methods in a constructor or a destructor (during construction or destruction, the dynamic dispatch considers that the object is of the exact type of current destructor).

    Moreover since the vtable changes during the destruction, acceding a virtual method from another thread may resolves in an undefined behavior (I am not really sure about the last sentence, please feel free to verify my statement).
    This issue can be solved by adding a final to the running method. (See Lomadriel@7821065)
    Since the final is in an upper class (module), the dynamic dispatch is not used. The call to running method is now statically resolved inside the timer_module class and so calling running is equivalent to a call to any non-virtual function.

    This issue is also present in event_module and inotify_module,
    https://github.com/jaagr/polybar/blob/7414e9800879cc3692af5ca217fdb18978ba8b4a/include/modules/meta/event_module.hpp#L32
    https://github.com/jaagr/polybar/blob/7414e9800879cc3692af5ca217fdb18978ba8b4a/include/modules/meta/inotify_module.hpp#L28
    1.2.
    https://github.com/jaagr/polybar/blob/7414e9800879cc3692af5ca217fdb18978ba8b4a/include/modules/meta/timer_module.hpp#L23-L26
    When update is called, build can't be called since the internal state is not protected.
    this must be:
const auto check = [&]() -> bool {
  std::lock(this->m_updatelock, this->m_buildlock);
  std::unique_lock<std::mutex> guard_update(this->m_updatelock, std::adopt_lock);
  std::unique_lock<std::mutex> guard_build(this->m_buildlock, std::adopt_lock);

  return CAST_MOD(Impl)->update();
};

This problem is also present in event_module, however the problem can't be solved in this class by using this patch since has_event from i3 module can block. (The best would be to remove this blocking comportment).

  1. CRTP problem
    Like virtual methods, it is not safe to call method from the derived class in a constructor or a destructor. Like in 1.1, such calls can happen during the destruction of a module since the thread is still running. So for example this whole loop is undefined behavior when the destructor is being called if the methods exist in the derived class:
    https://github.com/jaagr/polybar/blob/7414e9800879cc3692af5ca217fdb18978ba8b4a/include/modules/meta/timer_module.hpp#L33-L38
    I see two solutions to solve this problem:
  1. signal_emitter and signal_receiver:
    The map that stores the signal handlers is not protected (g_signal_receivers) and emit, attach and detach can be called at the same time.
    I tried to add a shared_timed_mutex to solve this problem, however since some handlers detach themselves when they receive an event this doesn't work (recursive_mutex can be a solution but this mutex must be avoided).
    A solution could be to lock the mutex, copy the handlers that must receive this event, unlock the mutex, send the event.
    Another solution could be to code something like Boost.Signal2 to do the job.
  2. tray_manager
    setup(const bar_settings&) and settings() are called at the same time.
    Trace:
    image
  3. pulseaudio adapter
    The events queue (m_events) is not protected so for example: wait() and subscribe_callback can be called at the same time.

There are other concurrency issues but some are related to the ones listed here.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions