【问题标题】:DOMDocument->save() fails after user_abort is handled处理 user_abort 后 DOMDocument->save() 失败
【发布时间】:2017-05-03 16:39:11
【问题描述】:

PHP 中,可能是register shutdown functions,在我的场景中,它(有时会被忽略)被定义为调用,见下文。

DOMDocument class in PHP 支持的 PHP/libxml 无法与我注册的 shutdown functions 配合使用,如果我想在 user abort 之后调用 ->save()->saveXML() 工作正常)(例如,从注册的 @987654329 @ 或类实例destructor)。相关的还有PHP connection handling

让例子说话:

PHP版本:

php --version
PHP 7.1.4 (cli) (built: Apr 25 2017 09:48:36) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

要重现 user_abort 我正在通过 python2.7 run.py:

运行 php
import subprocess

cmd = ["/usr/bin/php", "./user_aborted.php"]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)

# As this process exists here and the user_aborted.php
# has sleeps/blocks in for-cycle thus simulating a user-abort
# for the php subprocess.

php 脚本user_aborted.php 尝试在关机功能中保存 XML

<?php

ignore_user_abort(false);
libxml_use_internal_errors(true);

$xml = new DOMDocument();
$xml_track = $xml->createElement( "Track", "Highway Blues" );
$xml->appendChild($xml_track);

function shutdown() {
    global $xml;

    $out_as_str = $xml->saveXML();

    fwrite(STDERR, "\nout_as_str: " . var_export($out_as_str, true) . "\n");

    $out_as_file = $xml->save('out.xml');

    fwrite(STDERR, "\nout_as_file: >" . var_export($out_as_file, true) . "<\n");
    fwrite(STDERR, "\nerrors: \n" . var_export(libxml_get_errors(), true) . "\n");
}

register_shutdown_function('shutdown');

$i = 2;

while ($i > 0) {
    fwrite(STDERR, "\n PID: " . getmypid() . " aborted: " . connection_aborted());
    echo("\nmaking some output on stdout"); // so user_abort will be checked
    sleep(1);
    $i--;
}

现在,如果我在没有用户中止(仅调用 PHP)的情况下运行此脚本:
php user_aborted.phpXML 将正确保存

然而当通过python2.7(通过退出父进程模拟用户中止)调用时,python2.7 run.py会发生最奇怪的事情:

  • out_as_str 值很好,看起来是我想要的 XML
  • 但是文件out.xml 是一个空文件
  • 另外libxml_get_errors 报告 FLUSH 问题

带有 python 的输出看起来: python2.7运行.py

PID: 16863 aborted: 0
out_as_str: '<?xml version="1.0"?>
<Track>Highway Blues</Track>
'

out_as_file: >false<

errors:
array (
  0 =>
  LibXMLError::__set_state(array(
     'level' => 2,
     'code' => 1545,
     'column' => 0,
     'message' => 'flush error',
     'file' => '',
     'line' => 0,
  ))
) 

抱歉,这篇文章很长,但我整天都在查看 PHP/libxml2 代码,但没有任何成功。 :/

【问题讨论】:

  • $xml-&gt;save('out.xml'); 从类中调用时也会发生这种情况。
  • @andras.tim 对,我已经更新了标题/文字

标签: php xml libxml2 php-7


【解决方案1】:

原因:

事实证明这是由于修复了以前的错误。

链接:

链接的php_libxml_streams_IO_write 函数是writecallback(设置in ext/libxml/libxml.c),用于docp 对象的缓冲区,该对象被移交给ext/dom/document.c 上的libxml 调用。以libxml xmlIO.c 结束,其中缓冲区为NULL,因此为-&gt;save(*) 提供的文件不会被写入。

解决方法:

使用-&gt;saveXML() 获取字符串中的XML 表示,并使用file_put_contents(*) 通过“手”编写它:

$xml_as_str = $xml->saveXML();
file_put_contents('/tmp/my.xml', $xml_as_str);

【讨论】:

    猜你喜欢
    • 2012-10-18
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2013-06-10
    • 1970-01-01
    • 2022-07-29
    相关资源
    最近更新 更多