rcpputils icon indicating copy to clipboard operation
rcpputils copied to clipboard

ros2 bag play error on windows foxy - [rosbag2_transport]: Failed to play: cannot get file size

Open karthiknit1 opened this issue 1 year ago • 2 comments

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

karthiknit1 avatar Mar 07 '23 07:03 karthiknit1

@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

karthiknit1 avatar Mar 27 '23 10:03 karthiknit1

Thanks for debugging this. I think if you could add a test and a pull request in rcutils, we can continue the conversation there.

mjcarroll avatar Mar 27 '23 15:03 mjcarroll