Django服务器崩溃,退出代码为13977

2024-04-28 07:04:25 发布

您现在位置:Python中文网/ 问答频道 /正文

前言

好吧,我有一个非常复杂的性能问题。我正在构建一个内容管理系统,其中一个特性应该是使用不同的模板生成大量的.docx文件。我从Webodt+Abiword开始。但是模板变得太复杂了,所以我不得不把我的后端切换到Templated-docs+LibreOffice。我的问题是从哪里开始的。在

我使用:

  • Python 2.7.12版
  • Django==1.8.2
  • 模板化文档==0.2.9
  • 图书馆办公室5.1.5.2
  • Ubuntu 16.04

实际问题

我有一个处理.docx呈现的API。我将展示其中一个视图,作为示例,它们非常相似:

@permission_classes((permissions.IsAdminUser,))
class BookDocxViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    def retrieve(self, request, *args, **kwargs):
        queryset = Pupils.objects.get(id=kwargs['pk'])
        serializer = StudentSerializer(queryset)
        context = dict(serializer.data)
        doc = fill_template('crm/docs/book.ott', context, output_format='docx')
        p = u'docs/books/%s/%s_%s_%s.doc' % (datetime.now().date(), context[u'surname'], context[u'name'], datetime.now().date())
        with open(doc, 'rb') as f:
            content = f.read()
            path = default_storage.save(p, ContentFile(content))
            f.close()
        return response.Response(u'/media/' + path)

当我第一次调用它时,它会创建一个.docx文件,保存到我的default_storage中,然后返回一个下载链接。但是当我再次尝试这样做时,或者使用另一个方法(它可以与另一个模板和上下文一起工作),我的服务器就会在没有任何日志的情况下崩溃。我最后看到的是

  1. ^{cd5>稍等片刻再打电话
  2. Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)如果立即第二次调用我的方法(不到一秒钟)

我试着使用调试器——它说我的服务器在这一行崩溃了:

doc = fill_template('crm/docs/book.ott', context, output_format='docx')

我敢打赌发生的事情是:

  1. 当我第一次调用我的方法时,templated_docs启动LibreOffice后端,然后没有停止它
  2. 当我第二次调用我的方法时,templated_docs再次尝试启动LibreOffice后端,但它已经很忙了。在

问题

  1. 我如何调试LibreOffice来证明/反驳我的理论?(我想我需要调试templated_docs
  2. 为什么我得到不同的出口代码取决于延迟?在
  3. 在GitHub上oppen一个issue足够了吗?在
  4. 我怎么解决这个问题?在

UPD公司

这不是REST框架或不使用FileResponce()的问题。 我已经试过用常规视图来测试它了。在

^{pr2}$

问题是一样的。在


升级版2

好吧。这条线在攻击我的服务器:

# pylokit/lokit.py
self.lokit = lo.libreofficekit_hook(six.b(lo_path))

Tags: 文件path方法self服务器视图模板docs
1条回答
网友
1楼 · 发布于 2024-04-28 07:04:25

好吧,那是templated_docs中的一个错误。我是对的,这是因为templated_docs试图启动两次LibreOffice。正如它在pylokitdocumentation中所说:

The use of _exit() instead of default exit() is required because in some circumstances LibreOffice segfaults on process exit.

这意味着使用pylockt的进程应该在之后被终止。但我们不能杀死Django服务器。所以我决定使用多重处理:

# templated_docs/__init__.py

if source_extension[1:] != output_format:
    lo_path = getattr(
        settings,
        'TEMPLATED_DOCS_LIBREOFFICE_PATH',
        '/usr/lib/libreoffice/program/')

    def f(conn):
        with Office(lo_path) as lo:
            conv_file = NamedTemporaryFile(delete=False,
                                           suffix='.%s' % output_format)
            with lo.documentLoad(str(dest_file.name)) as doc:
                doc.saveAs(conv_file.name)
            os.unlink(dest_file.name)
            conn.send(conv_file.name)
            conn.close()

    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    conv_file_name = parent_conn.recv()
    p.join()

    return conv_file_name
else:
    return dest_file.name

我反对一个issue,做了一个pull request。在

相关问题 更多 >