BaseT is a proof of concept stream handler I wrote on a whim. I was wondering if you can reload code in PHP without using runkit or separate processes and so this design was born. The aim was to write a quick IRC bot but the base code is so generic it can probably handle any line based streams. A few example plugins are included.
The reloading works by putting all code in anonymous functions (this forbids the use of classes, constants and similar structures in plugins) and just re-including all the plugin files upon a reload. There are a few builtin hooks to attach code to and you can add your own, because you can also reload core code in the utils.php file. Note that there is no error handling so any fatal error – like a parse error during reload – will crash the whole thing.
I am not familiar with PHP internals regarding the loading of code for closures, namely will PHP actually delete code attached to a closure when the last reference to its variable is gone, so I cannot say there are no memory leaks. My empirical testing suggests that the memory use jumps up and down after reloads, but eventually grows slightly after many reloads. You can try to follow memory use with the plugin 9997_memoryusage.php.
BaseT should work on PHP 5.3+. It uses signals to force a reload so you'll need the pcntl extension, unless you delete the functions at the end of utils.php (and the declare at the top of main.php).
The main loop of the program will exit if there are no streams to handle, so you need to write a plugin to open a stream when the program is started. You can check $_started to see if the program is starting up for the first time. The plugin 0020_autojoin.php will have an example of this.
To reload code, send the program a SIGUSR1. The currently executing code will be interrupted, the reload will be scheduled to happen on the next iteration of the main loop and your code execution will be resumed. Note that an incoming signal can interrupt vital functions in your code and break things, so you may want to block signal handling at some points.
When writing plugins, you need to watch out for name clashes with variables, it's probably best to prefix your variables with a plugin identifier to avoid that. Plugins are included in ascending filename sort order so you can use numbers to order them the way you want.
This is a terrible way to write a program
I know, this was mostly a proof of concept on reloading code and a fun little thing to write. This is not what PHP was made for so don't expect great performance or stability (though it looks relatively stable with a small amount of plugins).
MIT, look at the LICENSE file.