2017-05-03 55 views
1

PHP中,它可能为register shutdown functions,但在我的场景中(有时会被忽略)在我的场景中定义调用,请参见下文。由DOMDocument class in PHP支持处理user_abort后,DOMDocument-> save()失败

PHP/libxml的不玩沿着井w /我的注册shutdown functions,如果我想(从注册shutdown function或一个类的实例destructor例如)user abort之后调用->save()->saveXML()正常工作)。相关的也是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我运行PHP通过python2.7run.py

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. 

The 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--; 
} 

,如果我运行此脚本W/O用户中止(简单地调用PHP)与:
php user_aborted.phpXML得到妥善保存

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

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

输出瓦特/蟒的样子: python2.7 run.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代码整天无任何成功。 :/

+0

这发生在'$ XML->保存(” out.xml');'也从一个类的破坏中调用。 –

+0

@ andras.tim对,我更新了标题/文本 – p1100i

回答

1

原因:

事实证明,这是由于对先前的错误修复。

链接:

链接的php_libxml_streams_IO_write函数是writecallback(设置in ext/libxml/libxml.c)为docp对象,它被移交的libxml呼叫的缓冲器在ext/dom/document.c。结束于libxml xmlIO.c,其中缓冲区为NULL,因此给出的->save(*)文件未写入。

解决方法:

使用->saveXML()得到的字符串中的XML表示并以 “手” 用file_put_contents(*)写:

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