<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Weird rocketry &#187; legacy</title>
	<atom:link href="http://webapp.org.ua/tag/legacy/feed" rel="self" type="application/rss+xml" />
	<link>https://webapp.org.ua</link>
	<description>Flights to outer code</description>
	<lastBuildDate>Sat, 16 Jul 2016 11:12:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Running php 5.2 fpm on ARM processor</title>
		<link>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/</link>
		<comments>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/#comments</comments>
		<pubDate>Sun, 20 Mar 2016 20:06:57 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[armhf]]></category>
		<category><![CDATA[fpm]]></category>
		<category><![CDATA[legacy]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scaleway]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=439</guid>
		<description><![CDATA[Sometimes you need to run legacy php code on ARM processors. Since php 5.2 was released 2 November 2006 at the time there were not a lot of powerful ARM solutions capable of running full-fledged websites. However, right now there is a possibility to run pretty heavy code on modern ARM platforms and a lot [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p>Sometimes you need to run legacy php code on ARM processors. Since php 5.2 was released 2 November 2006 at the time there were not a lot of powerful ARM solutions capable of running full-fledged websites. However, right now there is a possibility to run pretty heavy code on modern ARM platforms and a lot of linux distros support ARM architecture. There is even <a href="https://www.scaleway.com/">dedicated ARM cloud hosting</a>.</p>
<p>In this post we&#8217;re going to fix the inability to run PHP in the FPM(Fast Process Manager) mode which is an absolute requirement if you want to run production websites.</p>
</div>
<p><span id="more-439"></span></p>
<div class="markdown-content">
<h2>Compiling from sources</h2>
<p>Since there is no old php releases in modern linux distros we&#8217;re obviously going to compile everything from scratch. For our purposes we&#8217;ll use <code>ubuntu 15.04</code>, let&#8217;s download php sources from PHP museum:</p>
<pre><code class="bash" title="">$ mkdir -p /mnt/build/ &amp;&amp; cd /mnt/build/
$ wget http://museum.php.net/php5/php-5.2.17.tar.gz &amp;&amp; tar -xf php-5.2.17.tar.gz
$ apt-get install -y build-essential nano wget curl libbz2-dev libncurses5-dev autoconf libxml2-dev

</code></pre>
<h2>PHP-FPM patch</h2>
<p>For historical reasons, Fast Process Manager(FPM) for 5.2.X branch exists only in the <a href="http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz">form of patch</a>. Let&#8217;s download this patch and apply it the most recent 5.2 version:</p>
<pre><code class="bash" title="">$ cd php-5.2.17/
$ wget http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz &amp;&amp; gzip -d php-5.2.17-fpm-0.5.14.diff.gz
$ patch -p1 &lt; php-5.2.17-fpm-0.5.14.diff
 patching file configure
Hunk #7 succeeded at 110645 (offset 1324 lines).
Hunk #8 succeeded at 118930 (offset 1324 lines).
Hunk #9 succeeded at 119634 (offset 1324 lines).
Hunk #10 succeeded at 119689 (offset 1324 lines).
patching file configure.in
patching file libevent/ChangeLog
patching file libevent/Makefile.am
patching file libevent/Makefile.in
patching file libevent/README
patching file libevent/aclocal.m4

</code></pre>
<p>After this operation <code>--enable-fpm</code> option becomes available in <code>./configure</code> script:</p>
<pre><code class="bash" title="">$ ./configure --help | grep "fpm"
  --enable-fpm              FastCGI: If this is enabled, the fastcgi support
  --with-fpm-conf=PATH        Set the path for php-fpm configuration file [PREFIX/etc/php-fpm.conf]
  --with-fpm-log=PATH         Set the path for php-fpm log file [PREFIX/logs/php-fpm.log]
  --with-fpm-pid=PATH         Set the path for php-fpm pid file [PREFIX/logs/php-fpm.pid]

</code></pre>
<p>Let&#8217;s try to compile php with FPM support:</p>
<pre><code class="bash" title="">$ ./configure --prefix=/opt/php52 --enable-fastcgi --enable-fpm

loading cache ./config.cache
checking for Cygwin environment... no
checking for mingw32 environment... no
checking for egrep... grep -E
checking for a sed that does not truncate output... /bin/sed
checking host system type... armv7l-unknown-linux-gnueabi
checking target system type... armv7l-unknown-linux-gnueabi
checking for gcc... gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a cross-compiler... no
checking whether we are using GNU C... yes
....

Thank you for using PHP.

</code></pre>
<p>So far, everything is looking fine. Let&#8217;s try to build it by running <code>make</code> using 4 ARM cores to speedup process:</p>
<pre><code class="bash" title="">$ make -j4

/bin/sh /mnt/build/php-5.2.17/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/date/lib -Iext/date/ -I/mnt/build/php-5.2.17/ext/date/ -DPHP_ATOM_
INC -I/mnt/build/php-5.2.17/include -I/mnt/build/php-5.2.17/main -I/mnt/build/php-5.2.17 -I/mnt/build/php-5.2.17/ext/date/lib -I/usr/include/libxml2 -I/mnt/bu
ild/php-5.2.17/TSRM -I/mnt/build/php-5.2.17/Zend    -I/usr/include -g -O2  -c /mnt/build/php-5.2.17/ext/date/php_date.c -o ext/date/php_date.lo
/bin/sh /mnt/build/php-5.2.17/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/date/lib -Iext/date/ -I/mnt/build/php-5.2.17/ext/date/ -DPHP_ATOM_
INC -I/mnt/build/php-5.2.17/include -I/mnt/build/php-5.2.17/main -I/mnt/build/php-5.2.17 -I/mnt/build/php-5.2.17/ext/date/lib -I/usr/include/libxml2 -I/mnt/bu
ild/php-5.2.17/TSRM -I/mnt/build/php-5.2.17/Zend    -I/usr/include -g -O2  -c /mnt/build/php-5.2.17/ext/date/lib/astro.c -o ext/date/lib/astro.lo

..........

/mnt/build/php-5.2.17/ext/dom/node.c: In function ‘dom_canonicalization’:
/mnt/build/php-5.2.17/ext/dom/node.c:1953:21: error: dereferencing pointer to incomplete type ‘xmlBuf {aka struct _xmlBuf}’
    ret = buf-&gt;buffer-&gt;use;
                     ^
Makefile:553: recipe for target 'ext/dom/node.lo' failed
make: *** [ext/dom/node.lo] Error 1

</code></pre>
<h2>libxml2 patching</h2>
<p>And boom! We&#8217;re stuck with the first error: <code>dereferencing pointer to incomplete type xmlBuf {aka struct _xmlBuf}</code>. After googling around, the problem seems to be related to <code>libxml2</code> incompatibility and is <a href="https://code.google.com/archive/p/php52-backports/issues/16">well documented</a>. Let&#8217;s fix that error by applying yet another patch:</p>
<pre><code class="bash" title="">$ wget https://github.com/bananos/dockerized/raw/master/armbuild-php52/patches/libxml29_compat.patch
$ patch -p1 &lt; libxml29_compat.patch
patching file ext/dom/node.c
Hunk #1 succeeded at 1950 (offset 55 lines).
patching file ext/dom/documenttype.c
Hunk #1 succeeded at 215 (offset 10 lines).
patching file ext/simplexml/simplexml.c
Hunk #1 succeeded at 1343 (offset -74 lines).

</code></pre>
<p>And run <code>make</code> once again:</p>
<pre><code class="bash" title="">$ make -j4

......

In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:8:0,
                 from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_children.c:28:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2: error: #error unsupported processor. please write a patch and send it to me
 #error unsupported processor. please write a patch and send it to me
  ^
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:66:32: error: unknown type name ‘atomic_t’
 static inline int fpm_spinlock(atomic_t *lock, int try_once)
                                ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_children.c:28:0:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:16:3: error: unknown type name ‘atomic_t’
   atomic_t lock;
   ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:8:0,
                 from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_worker_pool.c:15:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2: error: #error unsupported processor. please write a patch and send it to me
 #error unsupported processor. please write a patch and send it to me
  ^
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:66:32: error: unknown type name ‘atomic_t’
 static inline int fpm_spinlock(atomic_t *lock, int try_once)
                                ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_worker_pool.c:15:0:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:16:3: error: unknown type name ‘atomic_t’
   atomic_t lock;
   ^
Makefile:433: recipe for target 'sapi/cgi/fpm/fpm_worker_pool.lo' failed
make: *** [sapi/cgi/fpm/fpm_worker_pool.lo] Error 1
make: *** Waiting for unfinished jobs....
Makefile:431: recipe for target 'sapi/cgi/fpm/fpm_children.lo' failed
make: *** [sapi/cgi/fpm/fpm_children.lo] Error 1

</code></pre>
<p>Well, this is embarrassing. As we can see from compiler logs, the FPM author suggests us to write a patch and send it to him because current CPU type is not supported. Obviously, the first thing I did was to try google yet another patch to solve this problem, but unfortunately, there is no one &#8212; people moved on to newer PHP versions and no one cared enough to write a fix.</p>
<p>Therefore, we&#8217;re going to write our own patch. Let&#8217;s take a look at <code>/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2</code></p>
<pre><code class="cpp" title="">

  /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
  /* (c) 2007,2008 Andrei Nigmatulin */

#ifndef FPM_ATOMIC_H
#define FPM_ATOMIC_H 1

#include &lt;stdint.h&gt;
#include &lt;sched .h&gt;

#if ( __i386__ || __i386 )

typedef int32_t                     atomic_int_t;
typedef uint32_t                    atomic_uint_t;
typedef volatile atomic_uint_t      atomic_t;

static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
{
        __asm__ volatile ( "lock;" "xaddl %0, %1;" :
                "+r" (add) : "m" (*value) : "memory");

        return add;
}

static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
{
        unsigned char res;

        __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
                "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");

    return res;
}

#elif ( __amd64__ || __amd64 )

// definitions of the same functions for AMD64

#else

#error unsupported processor. please write a patch and send it to me

#endif

</code></pre>
<h2>Atomic types</h2>
<p>Looks like we need to define those 2 functions for ARM platform. But how do we do it without proper knowledge of <code>C</code> and specifics of <code>armhf</code> architecture? Luckily, we may steal some code from newer PHP versions, which do work in FPM mode on ARM platform. Go to <code>https://github.com/php/php-src/blob/PHP-5.3/sapi/fpm/fpm/fpm_atomic.h</code> and take a look at source code:</p>
<pre><code class="cpp" title="">

    /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
    /* (c) 2007,2008 Andrei Nigmatulin */

#ifndef FPM_ATOMIC_H
#define FPM_ATOMIC_H 1

#if HAVE_INTTYPES_H
# include &lt;inttypes .h&gt;
#else
# include &lt;stdint .h&gt;
#endif
#include &lt;sched .h&gt;

#ifdef HAVE_BUILTIN_ATOMIC

/**
 * all the cases below (as provided by upstream) define:
 * word as atomic_int_t, and
 * unsigned word as atomic_uint_t
 * and only use volatile atomic_uint_t as atomic_t
 */

typedef volatile unsigned long atomic_t;
#define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c)

#elif ( __i386__ || __i386 )

///  a lot of platform-speicific definitions of above mentioned functions

#if (__GNUC__) &amp;&amp; (__GNUC__ &lt; 4 || (__GNUC__ == 4 &amp;&amp; __GNUC_MINOR__ &lt; 2))

#elif ( __arm__ || __arm ) /* W-Mark Kubacki */

///  other code we're not interested in

</code></pre>
<p>Although, it does contain the mention of ARM, the code defined for this case won&#8217;t be executed, since this is not our case:</p>
<pre><code class=" bash" title="">$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/5/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.2.1-22ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --enable-multilib --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-werror --enable-multilib --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)

</code></pre>
<p>What we&#8217;re going to do is leveraging built-in atomic types, which are controlled by <code>HAVE_BUILTIN_ATOMIC</code> flag. But first, let&#8217;s do a drop-in replacement of <code>fpm_atomic.h</code> from 5.3 branch:</p>
<pre><code class="" title="">$ cd /mnt/build/php-5.2.17/sapi/cgi/fpm
$ rm fpm_atomic.h &amp;&amp; wget "https://github.com/php/php-src/raw/PHP-5.3/sapi/fpm/fpm/fpm_atomic.h"

</code></pre>
<p>Another <code>magic</code> step is in fact, fix configure system to be able to enable above mentioned flag. Open <code>/mnt/build/php-5.2.17/sapi/cgi/fpm/acinclude.m4</code>  and add at the top:</p>
<pre><code class="" title="">AC_DEFUN([AC_FPM_BUILTIN_ATOMIC],
[
  AC_MSG_CHECKING([if gcc supports __sync_bool_compare_and_swap])
  AC_TRY_LINK(,
  [
    int variable = 1;
    return (__sync_bool_compare_and_swap(&amp;variable, 1, 2)
           &amp;&amp; __sync_add_and_fetch(&amp;variable, 1)) ? 1 : 0;
  ],
  [
    AC_MSG_RESULT([yes])
    AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Define to 1 if gcc supports __sync_bool_compare_and_swap() a.o.])
  ],
  [
    AC_MSG_RESULT([no])
  ])
])

</code></pre>
<p>After this is done, everything should compile just fine.</p>
<h2>TL;DR</h2>
<p>For those lazy folks who don&#8217;t want all the investigation details here&#8217;s an updated patch which I prepared:<br />
<code>https://github.com/bananos/dockerized/blob/master/armbuild-php52/patches/php-5.2.17-fpm-arm-0.5.14.diff</code></p>
<p>In order to use it, just download vanilla php-5.2.17 sources and apply the patch:</p>
<pre><code class="bash" title="">mkdir -p /tmp/build
cd /tmp/build &amp;&amp; wget http://museum.php.net/php5/php-5.2.17.tar.gz &amp;&amp; tar -xf php-5.2.17.tar.gz
cd /tmp/build &amp;&amp; wget https://github.com/bananos/dockerized/raw/master/armbuild-php52/patches/php-5.2.17-fpm-arm-0.5.14.diff
cd /tmp/build &amp;&amp; patch -p1 -d php-5.2.17/ &lt; /tmp/build/php-5.2.17-fpm-arm-0.5.14.diff

</code></pre>
<p>If you&#8217;re familiar with <a href="https://www.docker.com/">Docker</a> you may might also check precompiled and flattened <a href="https://github.com/bananos/dockerized/tree/master/armbuild-php52">PHP-5.2.17 ARMHF image</a><br />
with some most popular <code>PECL</code> packages pre-built.</p>
<p>Happy running your old legacy PHP code!</p>
<h2>Sources</h2>
<p>http://php-fpm.org/</p>
<p>https://github.com/bananos/dockerized/tree/master/armbuild-php52/</p>
<p>https://github.com/php/php-src/</p>
<p>https://code.google.com/archive/p/php52-backports/issues/16</p>
<p>http://saravananlinux.blogspot.com/2014/01/libxml-error-while-compiling-dual-php.html</p>
</div>
<p></sched></sched></stdint></inttypes></sched></p>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
