Changeset 1281 for python/trunk/Lib


Ignore:
Timestamp:
Dec 26, 2017, 10:43:44 PM (8 years ago)
Author:
dmik
Message:

python: Implement subprocess.Popen using LIBCx spawn2.

Closes #280.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • python/trunk/Lib/subprocess.py

    r1254 r1281  
    659659                 preexec_fn=None, close_fds=False, shell=False,
    660660                 cwd=None, env=None, universal_newlines=False,
    661                  startupinfo=None, creationflags=0):
     661                 startupinfo=None, creationflags=0,
     662                 threadsafe=None):
    662663        """Create new Popen instance."""
    663664        _cleanup()
     
    683684                raise ValueError("creationflags is only supported on Windows "
    684685                                 "platforms")
     686        if os2:
     687            if threadsafe is None:
     688                threadsafe = False
     689        else:
     690            if threadsafe is not None:
     691                raise ValueError("threadsafe is only supported on OS/2 "
     692                                 "platforms")
    685693
    686694        self.stdin = None
     
    713721            self._execute_child(args, executable, preexec_fn, close_fds,
    714722                                cwd, env, universal_newlines,
    715                                 startupinfo, creationflags, shell, to_close,
     723                                startupinfo, creationflags, threadsafe, shell, to_close,
    716724                                p2cread, p2cwrite,
    717725                                c2pread, c2pwrite,
     
    912920        def _execute_child(self, args, executable, preexec_fn, close_fds,
    913921                           cwd, env, universal_newlines,
    914                            startupinfo, creationflags, shell, to_close,
     922                           startupinfo, creationflags, threadsafe, shell, to_close,
    915923                           p2cread, p2cwrite,
    916924                           c2pread, c2pwrite,
     
    11951203        def _execute_child(self, args, executable, preexec_fn, close_fds,
    11961204                           cwd, env, universal_newlines,
    1197                            startupinfo, creationflags, shell, to_close,
     1205                           startupinfo, creationflags, threadsafe, shell, to_close,
    11981206                           p2cread, p2cwrite,
    11991207                           c2pread, c2pwrite,
     
    12231231                # in the kernel).
    12241232                mode = os.P_NOWAIT
    1225                 oldcwd = None
    1226                 dups = [ None, None, None ]
    1227                 cloexec_fds = set()
    1228 
    1229                 try:
    1230                     # Change the directory if asked
    1231                     if cwd is not None:
    1232                         oldcwd = os.getcwd()
    1233                         os.chdir(cwd)
    1234 
    1235                     # Duplicate stdio if needed
    1236                     if p2cread is not None:
    1237                         dups[0] = os.dup(0)
    1238                         os.dup2(p2cread, 0)
    1239                         self._set_cloexec_flag(dups[0])
    1240                     if c2pwrite is not None:
    1241                         dups[1] = os.dup(1)
    1242                         os.dup2(c2pwrite, 1)
    1243                         self._set_cloexec_flag(dups[1])
    1244                     if errwrite is not None:
    1245                         dups[2] = os.dup(2)
    1246                         os.dup2(errwrite, 2)
    1247                         self._set_cloexec_flag(dups[2])
    1248 
    1249                     # Disable inheritance
    1250                     if close_fds:
    1251                         for i in xrange(3, MAXFD):
    1252                             try:
    1253                                 f = fcntl.fcntl(i, fcntl.F_GETFD)
    1254                                 if not (f & fcntl.FD_CLOEXEC):
    1255                                     cloexec_fds.add(i)
    1256                                     self._set_cloexec_flag(i)
    1257                             except:
    1258                                 pass
    1259 
    1260                     if env is None:
    1261                         pid = os.spawnvp(mode, executable, args)
    1262                     else:
    1263                         pid = os.spawnvpe(mode, executable, args, env)
    1264                 finally:
    1265                     # Restore inheritance
    1266                     for i in cloexec_fds:
    1267                         self._set_cloexec_flag(i, False)
    1268 
    1269                     # Restore the parent stdio
    1270                     for i, fd in enumerate(dups):
    1271                         if fd is not None:
    1272                             os.dup2(fd, i)
    1273                             os.close(fd)
    1274 
    1275                     # Restore the current directory
    1276                     if oldcwd is not None:
    1277                         os.chdir(oldcwd)
     1233
     1234                if close_fds:
     1235                  mode |= os.P_2_NOINHERIT
     1236                if threadsafe:
     1237                  mode |= os.P_2_THREADSAFE
     1238                stdfds = [ p2cread, c2pwrite, errwrite ]
     1239
     1240                pid = os.spawn2(mode, executable, args, cwd, env, stdfds)
    12781241
    12791242                # Child is launched. Close the parent's copy of those pipe
     
    14801443                        data = _eintr_retry_call(file.read)
    14811444                        if data == "":
    1482                             file.close()
     1445                            try:
     1446                                file.close()
     1447                            except IOError as e:
     1448                                # kLIBC close may fail with EBADF or even Error 0,
     1449                                # ignore for now
     1450                                pass
    14831451                            break
    14841452                        buffer.append(data)
     
    15041472                    if input is not None:
    15051473                        try:
    1506                             self.stdin.write(input)
     1474                            _eintr_retry_call(self.stdin.write, input)
    15071475                        except IOError as e:
    15081476                            if e.errno != errno.EPIPE:
    15091477                                raise
    1510                     self.stdin.close()
     1478                    try:
     1479                        self.stdin.close()
     1480                    except IOError as e:
     1481                        # kLIBC close may fail with EBADF or even Error 0,
     1482                        # ignore for now
     1483                        pass
    15111484
    15121485                if self.stdout:
Note: See TracChangeset for help on using the changeset viewer.