我有一个django网络应用程序,它提供了一个C代码编辑器,文本被发送到托管在另一个服务器上的另一个django应用程序,该应用程序将代码写入.c文件中进行编译并发回响应。
问题是编写和编译文件会导致与多个用户一起使用该应用程序时出现竞争条件问题。
这是我发送数据的方式:
def comp(request):
encoded_data = urllib.urlencode(request.POST)
url = urllib2.urlopen('http://serverIpadress/compile/?' + encoded_data)
tml = url.read()
return HttpResponse(tml)
这是在第二个django应用程序上处理数据的方式
def compile(request):
data2=urllib.urlencode({'': request.GET.get('content','')})
request.encoding ='koi8-r'
data=request.GET.get('content','')
handle=open('/home/user/file.c','r+')
handle.write(request.GET['content'])
handle.close()
res = commands.getstatusoutput('gcc -Wall /home/user/file.c -o /home/user/file;home/user/file')
return HttpResponse(res)
我已经尝试使用信号量
sem = threading.BoundedSemaphore()
sem.aquire()
writing to file
compiling
sem.release()
但问题仍然存在
我已经找到了解决方案,但我发现的唯一解决方案是关于使用交易的数据库
感谢您的帮助
答案 0 :(得分:1)
似乎您为每个请求使用单个文件/home/user/file.c
。所以,竞争状态迫在眉睫。
有两种解决方案:
1)写入临时文件。临时文件可以从tempfile模块生成,也可以只创建随机文件名。
2)写入内存文件。您可以使用StringIO
(或更快的cStringIO
)模块来创建此类文件,然后将其传输到gcc。
对于解决方案1),有很多方法可以做到这一点,但这是我的解决方案:
更改此部分
data=request.GET.get('content','')
handle=open('/home/user/file.c','r+')
handle.write(request.GET['content'])
handle.close()
到
# you need 'random', 'string', 'os' modules imported
data=request.GET.get('content','')
filename = "".join(random.sample(string.letters, 10)) + ".c" #sample 10 letters from A-z
filepath = os.path.join('home','user','filename')
handle=open(filepath,'r+')
handle.write(request.GET['content'])
handle.close()
res = commands.getstatusoutput('gcc -Wall %s -o /home/user/file;home/user/file' %filepath)
os.remove(filepath) #remove temporary file after compiling
另外,commands
模块已弃用。你应该使用subprocess.call
。
答案 1 :(得分:0)
您应该为每个请求生成随机文件并使用它。 tempfile模块可以帮助您。
此外,如果您不关心生成的二进制文件,使用-o /dev/null
是个好主意。