backintime icon indicating copy to clipboard operation
backintime copied to clipboard

RuntimeError: reentrant call inside <_io.BufferedWriter name=''>

Open likg opened this issue 6 years ago • 5 comments

With backintime (1.2.0) when you try to backup whole system (/ mount point) backup task fails with the following error:

Back In Time
Version: 1.2.0

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

INFO: Lock
INFO: Take a new snapshot. Profile: 1 Main profile
INFO: Call rsync to take the snapshot
Traceback (most recent call last):
  File "/usr/share/backintime/common/backintime.py", line 1165, in <module>
    startApp()
  File "/usr/share/backintime/common/backintime.py", line 517, in startApp
    args.func(args)
  File "/usr/share/backintime/common/backintime.py", line 739, in backup
    ret = takeSnapshot(cfg, force)
  File "/usr/share/backintime/common/backintime.py", line 94, in takeSnapshot
    ret = snapshots.Snapshots(cfg).backup(force)
  File "/usr/share/backintime/common/snapshots.py", line 692, in backup
    ret_val, ret_error = self.takeSnapshot(sid, now, include_folders)
  File "/usr/share/backintime/common/snapshots.py", line 1036, in takeSnapshot
    proc.run()
  File "/usr/share/backintime/common/tools.py", line 1981, in run
    self.callback(line, self.user_data)
  File "/usr/share/backintime/common/snapshots.py", line 797, in rsyncCallback
    self.setTakeSnapshotMessage(0, _('Take snapshot') + " (rsync: %s)" % line)
  File "/usr/share/backintime/common/snapshots.py", line 143, in setTakeSnapshotMessage
    self.snapshotLog.append('[I] '  + message, 3)
  File "/usr/share/backintime/common/snapshotlog.py", line 195, in append
    self.logFile.write(msg + '\n')
  File "/usr/share/backintime/common/tools.py", line 1513, in handler
    self.callback()
  File "/usr/share/backintime/common/snapshotlog.py", line 203, in flush
    self.logFile.flush()
RuntimeError: reentrant call inside <_io.BufferedWriter name='/root/.local/share/backintime/takesnapshot_.log'>

Simple workaround in this case is to add backintime log file (e.g. /root/.local/share/backintime/takesnapshot_.log) to exclude list.

Please review this case, maybe log file should be excluded (or handled in a special way), to avoid such issue.

likg avatar May 21 '19 22:05 likg

Exact same issue, but in my case it was a backup from one mount point to another, the log file was not included in anyway. Also if you take a look at the log file itself, the rsync command already exclude it --exclude=/root/.local/share/backintime so it can't be the issue.

What I find weird is the way the rsync command is composed (for reference, running as root with only include /mnt/data/, to /mnt/backup/).

Why does it have to change the permissions? --chmod=Du+wx Why is this necessary? --exclude=.local/share/backintime/mnt

Edit: Weirdly enough a reboot solve the issue for me.

MAProsper avatar Jul 10 '19 21:07 MAProsper

I got the same issue as the downstream maintainer in fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1729773

hannes101 avatar Jul 29 '19 04:07 hannes101

I just had the exact same issue with the same backtrace, after backing up multiple terabytes of data over 24 hours. Please consider ignoring the log file unconditionally, as it is a very nasty surprise.

tatokis avatar Apr 22 '20 15:04 tatokis

Still happening on a recent fedora version with the latest upstream backintime https://bugzilla.redhat.com/show_bug.cgi?id=2016628

hannes101 avatar Oct 23 '21 07:10 hannes101

Same error with Backintime 1.3.2 running in Manjaro. Trying to backup files from one USB drive onto another USB drive.

rvega avatar Jun 09 '22 22:06 rvega

There may be useful hints in the closed OpenSUSE bug 1188115.

emtiu avatar Sep 25 '22 16:09 emtiu

another crash on fedora https://bugzilla.redhat.com/show_bug.cgi?id=2150491 Could this be caused by the reason, described in https://bugzilla.opensuse.org/show_bug.cgi?id=1188115#c4 ? So it would be possible to fix it by excluding the log file by default from the backup?

hannes101 avatar Dec 03 '22 16:12 hannes101

Reason for this bug

RuntimeError: reentrant call inside <_io.BufferedWriter ...

This is a known issue of Python3 and works as expected from the Python point-of-view ("won't fix") since this code is not reentrant: https://bugs.python.org/issue24283

Looking into the traceback I think this a non-deterministic bug in BiT that happens whenever BiT tries to write into the log file in the main thread while triggering a file buffer flush in another thread (via a "timer" signal) so excluding the BiT log file will not eliminate this RTE!

Code that causes the bug

The snapshot logger establishes a signal handler that is called in regular time intervals to flush the log file (in another thread!): https://github.com/bit-team/backintime/blob/f7f28b50b7decd8f7e8666c654c33fda387f2ea0/common/snapshotlog.py#L117

A log entry is written in the main thread and the signal handler instructed to be called after 5 secs to flush the file buffer: https://github.com/bit-team/backintime/blob/f7f28b50b7decd8f7e8666c654c33fda387f2ea0/common/snapshotlog.py#L195-L196

After 5 secs the flush method is called for the log file https://github.com/bit-team/backintime/blob/f7f28b50b7decd8f7e8666c654c33fda387f2ea0/common/tools.py#L1489

Whenever writing a snapshot log entry (snapshotlog.py#L195) is interrupted by the flush call we get the RTE with the traceback as reported here.

Proposed fix:

The Python3 runtime will not support reentrance and BiT should flush the log every n seconds to make the progress visible and persist the up-to-date log file content even if BiT crashes.

So the easiest fix is to catch this RTE in the flush method and log it as INFO only (and ignore it).

Edit: Logging of this RTE is not reliable since it would cause another RTE of the same type ;-)

I will prepare a PR to fix this.

Consider excluding BiT files from the backups

BiT uses rsync and this is not meant to backup all files of the whole system since open files may cause problems. but users want to to do this anyhow so ignoring BiT files in backups would be a good idea.

From what I see in the code

https://github.com/bit-team/backintime/blob/bff7aeb9fd07fb44f82ba5ba4ef2da5f0cc1d56c/common/config.py#L184-L189

the following folders should be excluded too by default (and manually as workaround for older versions of BiT):

  • /root/.local/share/backintime
  • /<currentuser>/.local/share/backintime

Ignoring specific files kept open by BiT would be even better since ignoring the whole folder means that

  • the configs (backup profiles) and
  • the user-callback script

are not contained in the backup :astonished:

This would require to add a positive list of all file names (or extensions) that are uses in the config.py (e.g. worker*.* files).

The default config can be changed here in the source code:

https://github.com/bit-team/backintime/blob/bff7aeb9fd07fb44f82ba5ba4ef2da5f0cc1d56c/common/config.py#L132-L135

aryoda avatar Dec 03 '22 19:12 aryoda

FYI: I have fixed the bug and opened a separate issue as feature request (#1382) to exclude BiT files by default so that this issue can be closed now.

aryoda avatar Dec 04 '22 23:12 aryoda

Thanks a lot! I am really impressed by the new BiT team, please keep up the good work!

hannes101 avatar Dec 05 '22 07:12 hannes101