Segfault when importing Python Module

オープン
#438 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
25/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
cmake, cpp, python

調査の方向性

carma_clock.h の C++ クラス、Boost.Python ラッパー、および提供された Python スクリプトを使用して、インポートと CarmaClock の構築を再現します。まず CMake でビルドされた共有ライブラリを調べ、core dump を gdb で使用して segfault の箇所を特定し、その後、モジュールのインポートと CarmaClock の構築がクラッシュせずに完了することを確認します。

索引モデルが issue の本文から書いたものです。

説明

Hello, I am attempting to wrap a C++ class using boost python into a python includable module. I am using CMake instead of bjam to build the project but I am running into a segfault when I attempt to include import the generated shared library into a python script.
Below is the class as well as the boost python wrapper code and the python script I am using to test this. The entire branch can be found here

/*
 * Copyright (C) 2023 LEIDOS.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

#pragma once

#include <memory>
#include <condition_variable>
#include <mutex>
#include <vector>


namespace fwha_stol::lib::time {

/** Alias for a timestamp in seconds. */
using timeStampSeconds = uint32_t;
/** Alias for a timestamp in milliseconds. */
using timeStampMilliseconds = uint64_t;
using sleepCVPair = std::pair<std::shared_ptr<std::condition_variable>, std::shared_ptr<std::mutex>>;
using sleepValuePair = std::pair<timeStampMilliseconds, sleepCVPair>;

/**
 * @brief Provides access to current time and various utilities. If a simulation is enabled, all time-related
 * functions reflect simulation time. Otherwise system time (via std::chrono::system_clock) is utilized.
 *
 * No interpolation is performed; the most recently received simulation time point is considered to
 * be current.
 */
class CarmaClock {
public:
    /**
     * @brief Create a clock instance using read time mode (default) or simulation mode.
     * @param simulation_mode bool flag to indicate whether clock is in simulation mode.
     */
    explicit CarmaClock(bool simulation_mode = false);
    /**
     * @brief Destructor
    */
    ~CarmaClock() = default;
    // Public move constructor and move assignment operator
    CarmaClock(const CarmaClock&) = delete; // Deleted copy constructor
    CarmaClock& operator=(const CarmaClock&) = delete; // Deleted copy assignment operator
    CarmaClock(CarmaClock&&) = delete; // Deleted move constructor
    CarmaClock& operator=(CarmaClock&&) = delete; // Deleted move assignment operator

public:
    /**
     * @brief Get the current time in seconds.
     * @return epoch time in seconds as a uint32_t.
    */
    timeStampSeconds nowInSeconds() const;
    /**
     * @brief Get the current time in milliseconds.
     * @return epoch time in milliseconds as a uint64_t.
    */
    timeStampMilliseconds nowInMilliseconds() const;

public:
    /**
     * @brief Update the clock time. First call to update will initialize the carma-clock
     * @attention only valid when in simulation mode.
     * @param current_time in milliseconds to update the clock to.
     * @throws std::invalid_argument exception if called while carma-clock is not in simulation
     * mode.
    */
    void update(timeStampMilliseconds current_time);

public:
    
    /**
     * @brief Return whether this instance is in simulation mode.
    */
    inline bool is_simulation_mode() const {return _is_simulation_mode; };

    /**
     * @brief Will block calling thread until carma-clock has been initiliazed 
     * with the first call to update. 
     * @attention Only relavent when clock is in simulation mode. If not, will
     * immediately unblock.
    */
    void wait_for_initialization();
    /**
     * @brief Sleep until future time.
     * @param future_time epoch timestamp in milliseconds to sleep until.
     * @throw std::invalid_argument if carma-clock is not initialized.
     */
    void sleep_until(timeStampMilliseconds future_time);

    /**
     * @brief Sleep for time_to_sleep in milliseconds.
     * @param time_to_sleep milliseconds from current time to sleep for.
    */
    void sleep_for(timeStampMilliseconds time_to_sleep);

private:
    // Current simulation time
    timeStampMilliseconds _current_time = 0;

    // Simulation mode
    bool _is_simulation_mode;

    // Initialization variables
    bool _is_initialized;
    // Mutex for conditional variable
    std::mutex _initialization_mutex;
    // Conditional_variable used to block one or multiple threads until 
    // carma-clock object is initialized. On initialization all threads are 
    // notified.
    std::condition_variable _initialization_cv;

    // sleep related items
    // Mutex for conditional variable
    std::mutex _sleep_mutex;
    // A vector of time, mutex and conditional variables used to
    // block calling threads until a certain time update. Each call 
    // to sleep_until, creates a new entry that includes a time, a conditional 
    // variable and a mutex for the conditional variable. On each incoming time update
    // , all vector entries with times smaller or equal to the incoming update are notified. 
    // NOTE: Each entry is only expected to have a single thread waiting on it so the relevant
    // time update will only notify a single thread for each entry. Multiple threads waiting on 
    // the same time should each have their one entry in this vector.
    std::vector <sleepValuePair> _sleep_holder;
};

}

#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include "carma_clock.h"

BOOST_PYTHON_MODULE(libcarma_clockd) {
    using namespace boost::python;
    class_<fwha_stol::lib::time::CarmaClock, boost::noncopyable>("CarmaClock", init<bool>(arg("simulation_mode")=false))
        .def("nowInSeconds", &fwha_stol::lib::time::CarmaClock::nowInSeconds)
        .def("nowInMilliseconds", &fwha_stol::lib::time::CarmaClock::nowInMilliseconds)
        .def("update", &fwha_stol::lib::time::CarmaClock::update,args("current_time"))
        .def("is_simulation_mode", &fwha_stol::lib::time::CarmaClock::is_simulation_mode)
        .def("wait_for_initialization",&fwha_stol::lib::time::CarmaClock::wait_for_initialization)
        .def("sleep_until",&fwha_stol::lib::time::CarmaClock::sleep_until,args("future_time"))
        .def("sleep_for",&fwha_stol::lib::time::CarmaClock::sleep_for,args("time_to_sleep"));
        init_module_libcarma_clockd();
}
#!/usr/bin/python3

import libcarma_clockd
print("Creating Clock Object")

clock = libcarma_clockd.CarmaClock(False)

I suspect this is either related to our constructor with default parameters or our use of std::thread or std::mutex. I am unsure how to continue debugging this issue other than looking at the core dumb with gdb. Any help would be greatly appreciated.

This is currently being built in Jammy dev containers using boost 1.74 and cmake version 3.27.7

主要言語
C++
スター
537
フォーク
223
平均マージ
11時間 22分
マージ済み PR(30日)
2

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

boostorg/python のほかの issue

boostorg/python の issue をすべて見る

似ている issue

C++ の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。