CPU consumption goes up indefintely as time goes when exposing a chaiscript function with state to C++


Hello everyone,

I am having a strange problem. I do not know if the problem is a bug in ChaiScript or wether I am doing something wrong.

Here it goes.

I have a task scheduler written in C++. The task scheduler goes something like this:

class Task {
   bool onUpdate(int elapsed);
   virtual bool doOnUpdate(int elapsed) = 0;

class FunctionTask : Task {
        std::function<bool (int)> updateFunc_;

        virtual bool doOnUpdate(int elapsed) override { return updateFunc_(elapsed); }

class TaskScheduler {
   //Noncopyable, nonmovable
    shared_ptr<Task> addTask(std::function<bool (int)> task);
    void run();

Now I have a function spawn, that is exposed to ChaiScript:

shared_ptr<Task> spawn(std::function<bool (int)> task) {
       shared_ptr<Task> taskPtr = createTask<FunctionTask>(std::move(task));
       return task;

I exposed spawn:

chai.add(fun(&spawn), "spawn");

I also expose the TaskScheduler addTask and run().

Now, from my script I do the following:

var makeChoiceTask = fun[inputSystem, gameView](unused) {//Wait for a menu choice
    if (menuChoice != 0) {
        return false
    else {
        return true
    return false


I have instrumented the binary and I see that, as time goes, the following function keeps being called every time more intensively:


My scheduler calls task->onUpdate(elapsed) which will eventually call the ChaiScript function. I cannot even figure out why this is happening, but I am completely sure and I verified in several ways that it is putting the chaiscript function in the TaskScheduler is what is triggering an increasingly intensive call to that function.


I have more information on this problem.

The problem is easy to reproduce with my TaskScheduler but I think it will be reproducible in many other ways. How to reproduce:

  1. use a function<> in C++ side.

  2. create a function in ChaiScript and pass that function to the C++ side. The function must contain state that is ChaiScript side and that state must be used inside the function. For example.

    var a = 10
    var myFunc = funa { a.to_string(); }

  3. call repeteadly the function in C++ side.

    //C++ side
    function<void ()> f;
    //assign to f myFunc from ChaiScript
    while (1) { f(); }

With these steps I am able to observe an ever increasing cpu usage until it reaches 100%.


I would expect that if you have a tight loop making function calls that this would consume 100% of the CPU, so I’m not sure the second example actually demonstrates what you want it to. Particularly since it should not be calling the operator=(Boxed_Value &&) function you are reference in the first example.

Do you by any chance have any more information since you last posted this?


My loop stops for n milliseconds in each iteration. I do the same in C++. In ChaiScript it seems to grow steadily as it loops, without doing anything. In C++ it does not happen. I tested it myself in Mac OS X. I really think it is representative of what should not happen, since that loop is stopping for n millisecs per iteration, unless I am not seeing the problem myself and making wrong assumptions.

You can see in makeMenuChoice this:


That should make the CPU not be 100% since most of the time it is idle.


Tried to reproduce like this:

// g++ -std=c++17 -I ../submodules/ChaiScript/include/ chaiscipt_call.cpp -o /tmp/chaiscript_call -pthread -ldl

#include <chaiscript/chaiscript.hpp>

#include <string>
#include <thread>
#include <chrono>  
#include <iostream>

int main() {
        chaiscript::ChaiScript chai;

                var i = 0;    
                var test = fun[i]() {
                        i += 1;
                        return i.to_string(); 

        using namespace std::chrono_literals;

        auto test = chai.eval< std::function<std::string()> >("test");
        while(true) {  
                std::cout << test() << '\r';

CPU utilization stays constant around 5% on old 4ghz Xeon. Used release 6.0.0 for testing.

EDIT: on debian linux


This is a full example that for sure triggered the problem: