[CRIU] [PATCH] p.haul: workaround bug in tarfile library

Nikita Spiridonov nspiridonov at odin.com
Mon Nov 16 09:01:55 PST 2015


Workaround tarfile library bug that leads to ownerless garbage
zero blocks in socket when tarfile constructed with socket as
file object to transfer tarballs over network.

Since memory socket used for both images copying to destination
and passing to criu for memory migration this bug affect criu
swrk process which read that zeroes left from tarfile library
and hang.

To workaround current problem receive all remaining data from
memory socket after tarfile object closed and discard it.

In future we can replace tarfile with some better library (current
case not the first workaround needed for tarfile to work correctly)
or implement images tranfer in criu.

Signed-off-by: Nikita Spiridonov <nspiridonov at odin.com>
---
 phaul/images.py |    2 ++
 phaul/util.py   |   16 ++++++++++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/phaul/images.py b/phaul/images.py
index a67b569..1b004d6 100644
--- a/phaul/images.py
+++ b/phaul/images.py
@@ -44,6 +44,8 @@ class untar_thread(threading.Thread):
 			tf = tarfile.open(mode="r|", fileobj=util.fileobj_wrap(self.__sk))
 			tf.extractall(self.__dir)
 			tf.close()
+			# Discard all remaining data in socket after tarfile closed
+			util.discard_sk_input(self.__sk)
 		except:
 			logging.exception("Exception in untar_thread")
 
diff --git a/phaul/util.py b/phaul/util.py
index bb9a8ac..00824d5 100644
--- a/phaul/util.py
+++ b/phaul/util.py
@@ -2,6 +2,7 @@ import os
 import fcntl
 import errno
 import logging
+import socket
 
 
 class fileobj_wrap:
@@ -23,6 +24,21 @@ class fileobj_wrap:
 		self.__sk.send(str)
 
 
+def discard_sk_input(sk):
+	"""Read all data from socket and discard it
+
+	Current helper function needed to workaround tarfile library bug that
+	leads to ownerless garbage zero blocks in socket when tarfile constructed
+	with socket as file object to transfer tarballs over network.
+	"""
+	try:
+		while True:
+			sk.recv(0x10000, socket.MSG_DONTWAIT)
+	except socket.error as e:
+		if e.errno != errno.EWOULDBLOCK:
+			raise e
+
+
 class net_dev:
 	def __init__(self, name=None, pair=None, link=None):
 		self.name = name
-- 
1.7.1



More information about the CRIU mailing list