rcpputils
rcpputils copied to clipboard
ros2 bag play error on windows foxy - [rosbag2_transport]: Failed to play: cannot get file size
when there is only rosbag2_2021_09_27-09_11_59.db3 file and no metadata.yaml file, when I tried to play the bag file using the command "ros2 bag play rosbag2_2021_09_27-09_11_59.db3", the following error is encountered in ROS 2 Foxy terminal on windows.
[ERROR] [1652675142.815790900] [rosbag2_transport]: Failed to play: cannot get file size: The file pointer cannot be set on the specified device or file.
As per the discussion here, this is an issue in rcpputils package - https://github.com/ros2/rosbag2/issues/1019.
This issue is seen happening only with larger bag files.
Expected Behavior Bag file should be played successfully.
Actual Behavior ros2 bag play rosbag2_2021_09_27-09_11_59.db3 ros2 bag info rosbag2_2021_09_27-09_11_59.db3 Both the above commands are leading to the below error on windows only: [ERROR] [1652675142.815790900] [rosbag2_transport]: Failed to play: cannot get file size: The file pointer cannot be set on the specified device or file.
To Reproduce ** Steps to reproduce the behavior, e.g.
record a bag file.(around 8GB) in ROS 2 Foxy terminal. play the bag using "ros2 bag play bagFileName". Here instead of bag folder, provide bag file name(.db3) System (please complete the following information) OS: Windows ROS 2 Distro: Foxy Version: Installed binary of latest Foxy
@clalancette This is a problem in underlying implementation of the rcpputils::fs::path::file_size() from ros2/rcpputils/src/filesystem_helper.cpp in particularly for Windows platform. I was able to get this issue fixed with the following change:
uint64_t path::file_size() const
{
if (this->is_directory()) {
auto ec = std::make_error_code(std::errc::is_a_directory);
throw std::system_error{ec, "cannot get file size"};
}
#ifdef _WIN32
// On Windows "stat" the struct stat returned by the stat function has a 32-bit size field (st_size)
// which can't handle file sizes larger than 2GB. To handle large files on Windows, use the
// _stati64 function instead of stat.
struct _stati64 stat_buffer;
const auto rc = _stati64(path_.c_str(), &stat_buffer);
if (rc != 0) {
std::error_code ec{errno, std::system_category()};
errno = 0;
throw std::system_error{ec, "cannot get file size"};
} else {
return static_cast<uint64_t>(stat_buffer.st_size);
}
#else
struct stat stat_buffer;
const auto rc = stat(path_.c_str(), &stat_buffer);
if (rc != 0) {
std::error_code ec{errno, std::system_category()};
errno = 0;
throw std::system_error{ec, "cannot get file size"};
} else {
return static_cast<uint64_t>(stat_buffer.st_size);
}
#endif
}
This change is applicable in following functions in ros2/rcpputils/src/filesystem_helper.cpp: path::is_directory(), path::is_regular_file() This change is also applicable in following functions in ros2/rcutils/src/filesystem.c: rcutils_is_directory(), rcutils_is_file(), rcutils_exists(), rcutils_is_readable(), rcutils_is_writable(), rcutils_is_readable_and_writable(), rcutils_get_file_size().
Could you review the above change and see if we can create a pull request with this fix.
Thanks, Karthik Reddy
Thanks for debugging this. I think if you could add a test and a pull request in rcutils
, we can continue the conversation there.