Hello, I stumbled upon this bug when writing a Python plugin. I think this is a ikiwiki bug, since I do not think my plugin does anything wrong.

Example

I set up an example wiki, containing the setup file and the plugin, on github.

  1. Clone the repository

     git clone https://github.com/paternal/ikiwiki-rpcbug.git
    
  2. Change to the right directory

     cd ikiwiki-rpcbug
    
  3. Add the right ikiwiki directory to PYTHONPATH

     export PYTHONPATH="$PYTHONPATH:$(dirname $(dpkg -L ikiwiki | grep proxy))"
    
  4. Build the wiki

     ikiwiki --setup wiki.setup --rebuild
    
  5. The problem is in page http://localhost/~USERNAME/ikiwiki_bug_rpc/foo/ (for instance, http://localhost/~USERNAME/ikiwiki_bug_rpc is fine.

Problem

Page foo contains the directive [[!rpcbug ]] (rpcbug being the name of the plugin). Calling proxy.rpc("srcfile", "bar") in the preprocess function seems to mess up the RPC communication between ikiwiki and the plugin, and the result is that the generate foo/index.html page is a text file containing the return value of the preprocess call.

What I do not understand is that disabling the format function (by commenting line 46 of the plugin) solves the problem. Half of an explaination is that I think that when the the proxy.rpc function is called, the RPC communication is messed up in such a way that the format function is not called, and the return value of preprocess is considered to be the whole html code of the resulting page.

I understood that: as the first rpc call messes up the communication, more rpc calls are messed up, but if there is only one rpc call, not that much is broken. -- Louis

I hope someone will understand the problem better than I do, because I have no idea about how to solve this.

Regards,
-- Louis

I used the debug feature provided with proxy.py and rebuilt the wiki. I ran this with this version of my minimal bug example.

  • The bug happens in function preprocess (in call to srcfile, to be more precise).
  • The directive causing the bug is called on page foo.
  • Communication between Ikiwiki and the plugin is here.
  • The resulting HTML (for page foo) looks like:

[[!rpcbug Erreur: internal error: foo cannot be found in /home/louis/projets/ikiwiki/rpcbug or underlay]]

Calling srcfile(foo): page
Calling srcfile(README.md): /home/louis/projets/ikiwiki/rpcbug/README.md

My analysis:

  • The call to srcfile(foo) fails (because Ikiwiki thinks that page foo does not exist).
  • Ikiwiki thinks that processing of the directive is finished, whereas the plugin still waits for the answer of Ikiwiki.
  • Ikiwiki asks the plugin to render a new directive, but the plugin interprets the request as the return value for its previous request. Thus, the plugin thinks that srcfile(foo) is page (this page being a misinterpretation of the Ikiwiki request).

So, I think that this might be an error in the rpc_call function of the external plugin: when the called method fails, it should return something (or raise an exception, if this is possible in RPC) to notify the plugin that something went wrong.

-- Louis

Update: This can actually be a proxy error. Indeed:

  • Ikiwiki sends a methodCall message to the plugin (which is a call to the preprocess function);
  • the plugin sends a methodCall message to ikiwiki (which is a call to the srcfile function);
  • Ikiwiki answers with a methodCall message:
    • Ikiwiki answers this because the function call failed, and it is already processing the next directive;
    • the plugin thinks that it is its request answer, and misinterprets it.

Thus, I think that the bug is in the proxy.py python file. On receiving a methodCall (instead of a methodResponse) as an answer to a methodCall request, proxy.py should notice the type of request, and call the requested function.

I know Python better than I know Perl, so I can try to fix this.

-- Louis

Available in a git repository branch.
Branch: spalax/paternal/rpcbug
Author: Louis
I fixed this bug in a branch on my Ikiwiki clone. Please review :)

-- Louis