@@ -869,10 +869,28 @@ def _create_rlock(count, owner, *args): #XXX: ignores 'blocking'
869869 return lock
870870
871871# thanks to matsjoyce for adding all the different file modes
872- def _create_filehandle (name , mode , position , closed , open , strictio , fmode , fdata ): # buffering=0
872+ def _create_filehandle (name , mode , position , closed , open , strictio , fmode , fdata , owner_id = None ): # buffering=0
873873 # only pickles the handle, not the file contents... good? or StringIO(data)?
874874 # (for file contents see: http://effbot.org/librarybook/copy-reg.htm)
875875 # NOTE: handle special cases first (are there more special cases?)
876+ if owner_pid :
877+ # Handle unnamed temporary file in Linux
878+ #NOTE: Windows doesn't have it, other *nixes require C extensions.
879+ self_pid = os .getpid ()
880+ self_id = (self_pid , _process_create_time (self_pid ))
881+ if owner_id != self_id :
882+ # If the fd is from this process, go on, else:
883+ owner_pid = owner_id [0 ]
884+ if owner_id [1 ] == _process_create_time (owner_pid ):
885+ # Creation times are equal or both are None.
886+ # The fd is likely from a process in this machine.
887+ name = '/proc/%d/fd/%s' % (owner_pid , name )
888+ if not os .path .exists (name ):
889+ name = '<fdopen>'
890+ else :
891+ # The fd is from a finished process or not from this machine.
892+ name = '<fdopen>'
893+
876894 names = {'<stdin>' :sys .__stdin__ , '<stdout>' :sys .__stdout__ ,
877895 '<stderr>' :sys .__stderr__ } #XXX: better fileno=(0,1,2) ?
878896 if name in list (names .keys ()):
@@ -888,7 +906,7 @@ def _create_filehandle(name, mode, position, closed, open, strictio, fmode, fdat
888906 raise ValueError ("invalid mode: '%s'" % mode )
889907 try :
890908 exists = os .path .exists (name )
891- except :
909+ except Exception :
892910 exists = False
893911 if not exists :
894912 if strictio :
@@ -1407,6 +1425,39 @@ def save_attrgetter(pickler, obj):
14071425 log .info ("# Ag" )
14081426 return
14091427
1428+ def _process_create_time (pid ):
1429+ """process creation time in seconds since boot"""
1430+ try :
1431+ return _process_create_time .cache [pid ]
1432+ except KeyError :
1433+ pass
1434+ try :
1435+ import math
1436+ ticks_per_second = os .sysconf ('SC_CLK_TCK' )
1437+ ndigits = math .ceil (math .log10 (ticks_per_second ))
1438+ try :
1439+ from psutil import Process
1440+ psutil_time = psutil .Process (pid ).create_time ()
1441+ # psutil adds the boot_time to create_time.
1442+ # We don't care (and it could potentially drift with NTP).
1443+ create_time = create_time - psutil .boot_time ()
1444+ except ImportError :
1445+ with open ('/proc/%d/stat' % pid ) as file :
1446+ stat = file .read ()
1447+ # based on psutil and man proc
1448+ fields = stat .rpartition (')' )[2 ].split ()
1449+ starttime = float (fields [19 ])
1450+ create_time = starttime / ticks_per_second
1451+ except Exception as error :
1452+ log .debug ("_process_create_time() exception: %s" , error )
1453+ create_time = None
1454+ if create_time :
1455+ # Deal with float imprecision and time drift, we don't need full precision.
1456+ create_time = math .trunc (round (create_time , ndigits ))
1457+ _process_create_time .cache [pid ] = create_time
1458+ return create_time
1459+ _process_create_time .cache = {}
1460+
14101461def _save_file (pickler , obj , open_ ):
14111462 if obj .closed :
14121463 position = 0
@@ -1428,12 +1479,13 @@ def _save_file(pickler, obj, open_):
14281479 else :
14291480 strictio = False
14301481 fmode = 0 # HANDLE_FMODE
1431- pickler .save_reduce (_create_filehandle , (obj .name , obj .mode , position ,
1432- obj .closed , open_ , strictio ,
1433- fmode , fdata ), obj = obj )
1482+ args = (obj .name , obj .mode , position , obj .closed , open_ , strictio , fmode , fdata )
1483+ if isinstance (obj .name , int ):
1484+ pid = os .getpid ()
1485+ args += (pid , _process_create_time (pid ))
1486+ pickler .save_reduce (_create_filehandle , args , obj = obj )
14341487 return
14351488
1436-
14371489@register (FileType ) #XXX: in 3.x has buffer=0, needs different _create?
14381490@register (BufferedRandomType )
14391491@register (BufferedReaderType )
0 commit comments