korylprince
korylprince

Reputation: 3009

Main Python Process is stopped using subprocess calls in SocketServer

I am trying to implement a sort of reverse terminal: start server.py on some computer foo.

On some other computer run nc foo 2000 and you are connected to a bash shell on foo.

I am using the following server code:

import socket,os,threading,select,subprocess                                                                                             

class mysocket(socket.socket):

    def __init__(self,*arg, **kw):
        super(mysocket,self).__init__(*arg, **kw)
        self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.setblocking(0)


    def read(self):
        return self.recv(2048)

    def write(self,data):
        self.send(data)

    def accept(self):
        conn,addr = super(mysocket,self).accept()
        return mysocket(_sock=conn),addr

socket.socket = mysocket

import SocketServer

class RequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        subprocess.call(['bash','-i'],env=os.environ,stdin=self.request,stdout=self.request,stderr=self.request)

class ForkedTCPServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
    pass

if __name__ == '__main__':

    address = ('0.0.0.0', 2000) # let the kernel give us a port
    server = ForkedTCPServer(address, RequestHandler)

    server.serve_forever()

This works great if you only do one connection at a time.

However when I open a second connection, the nc program sits waiting, and my python process has the message:

[1]+  Stopped                 python server.py

If I type %1 to bring the process to the foreground, then the second nc screen starts working and I have two remote bash shells.

My question is why does the python process get stopped, and how can I stop it from happening?

As far as I can tell nothing is blocking, because once I resurrect the process everything works perfectly!

Thanks much.

Upvotes: 0

Views: 413

Answers (1)

korylprince
korylprince

Reputation: 3009

I figured it out. The problem was with calling bash, as other things would work.

Eventually on a whim I tried calling bash with the script command and it worked as expected.

Here is some final code for anyone who wants it:

import socket,os,threading,subprocess                                                                                                    

class mysocket(socket.socket):

    def __init__(self,*arg, **kw):
        super(mysocket,self).__init__(*arg, **kw)
        self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    def read(self):
        return self.recv(2048)

    def write(self,data):
        self.send(data)

    def accept(self):
        conn,addr = super(mysocket,self).accept()
        return mysocket(_sock=conn),addr

socket.socket = mysocket

import SocketServer

class RequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        subprocess.call('script -q -f -c "bash -i" /dev/null',shell=True,env=os.environ,stdin=self.request,stdout=self.request,stderr=self.request)

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

if __name__ == '__main__':
    address = ('0.0.0.0', 2000)
    server = ThreadedTCPServer(address, RequestHandler)
    server.serve_forever()

Note that this does not work on windows because of python's lack of support for using sockets as files on that platform. However it works perfectly on cygwin. Just install python and util-linux (for the script command) from cygwin's setup.exe.

Upvotes: 2

Related Questions