8

I am using pthreads to creat multiple threads. Each of those threads at one point tries to use get_posts() as follows:

$args = array(
    'post_type' => 'post',
    'post_status' => 'any'
);

$posts_list = get_posts($args);

However I end up with the following crash:

HP Fatal error:  Call to a member function get() on a non-object in C:\dev\wordpress\wp-includes\cache.php on line 123

PLEASE NOTE when I make the same get_posts() call in a code section that is not threaded, I do not have the crash.

Now, my question, how to call get_posts() from within a pthread thread? And if I cannot do that, what is the alternative?

Thanks.


Update

Here is sample code

class My_Thread extends Thread {

    public function run() {

        /* DO SOME STUFF HERE */

        $args = array(
            'post_type' => 'post',
            'post_status' => 'any'
        );

        $posts_list = get_posts($args); // <------ This is causing the crash
    }
}

// Create a array
$threads = array();

//Iniciate Miltiple Thread
foreach ( range("A", "C") as $i ) {
    $threads[] = new My_Thread($i);
}

// Start The Threads
foreach ($threads as $thread) {
    $thread->start();
}
12
  • that is not a crash it is an error..... you should fix your code so there will not be an error. In any case php libraries are not always multitasking safe so the problem might be with something totally different. Dec 24 '15 at 8:27
  • To add, if there is code that needs to be protected for "same time" execution than you need to use mutexes but that is way out off scope here. Dec 24 '15 at 8:29
  • @MarkKaplun - Thanks for your input. However, it seems like you missed the point where I state that "when I make the same get_posts() call in a code section that is not threaded, I do not have the crash"; so it is not a problem with my get_posts($args) call. Moreover, there isn't code that needs to be protected at this point, I am just reading from the WordPress DB via get_posts($args).
    – Greeso
    Dec 24 '15 at 8:38
  • 3
    @MarkKaplun - What's wrong with you? Why are you so negative and so aggressive? Why do you assume I don't understand multitasking and suggest that I should not use pthreads? Even if you are correct, aren't we supposed to try what we don't understand to expand our knowledge and limits? And isn't this site about asking questions if you do not know how you do a certain thing? I am not pretending anything. I ecountered an error, I realized it is due to using pthreads, and I am asking for a solution, either a setup or a a programming workaround. I was hoping for a constructive answer from yourself.
    – Greeso
    Dec 24 '15 at 15:38
  • 2
    Until we really know that WordPress isn't the reason to break this code, it is on topic.
    – fuxia
    Dec 25 '15 at 1:19
2

Since there are so many upvotes to the question, although the issues of multithreading are just too broad for a format of an answer, I will try to explain why you should not use wordpress API in a multithreaded way....

TL;DR - PHP is not assumed to be multithreading ready, the problem is not PHP itself but mainly the libraries it uses. This is why it is recommended not to use the multithreaded execution mode in apache although in theory it should be somewhat faster. To add to the problem of underlying layer not being multithread ready, wordpress core violates the most basic requirement of multithread- no free access to globals.

What is the problem with globals in multithreaded enviroment? lets assume we have the naive looking code

function inc() {
  global $g;

  $g++;
}

While it is just a one liner, it is not an atomic operation for the CPU, and it take several machine level instruction to actoally execute it. Some thing like

move $g to register D
increment register D
move register D to $g

Now lets assume we have two threads A B that call inc() at the "same time" (obviously with only one CPU there is no such thing as same time), and that the initial value of $g is 0, what would be the value of $g after both threads finished? It will depend on how the OS handles multithreading, when does it switch between threads. In "older" style OSes it was the job of the thread to declare by calling an API that control can be taken from it, but that leads to many problems with bad behaving processes locking down the system therefor in "modern" OS the OS takes control when ever it feels like it. In real life the result of the code will be that $g will have a value of 2, but there is also the following possibility

In the context of A

move $g to register D
// value of D is 0
// OS stores the content of registers and switches to thread B
// B increments $g to 1 and finishes working
// OS restores content of registers to the context of thread A
// Value of register D is now 0
increment register D
move register D to $g

End result is that $g has the value of 1.

Obviously globals are not the only problem and handling inputs and outputs is also a core for mutithreading problems.

In proper multithreading code you use lock/mutex/semaphore/pipe/socket.... to serialize access to such global resources to make sure there will be a predictable result to the operation. Wordpress do not do that.

Hell, wordpress is not even multi process safe. Most of the time it gets away with it because the DB schema is built in a way which in real life usage prevents the need to modify the same data from different processes (different posts has different rows and do not share data), but look at the sidebar/widgets code and try to imagine what will happen if two admins would try to add a different widget at exactly the same time. Since this will require the manipulation of one specific option the end result can be either both widgets added or only one of them.

Back to multithrading. In unix, unlike windows, the additional cost of spawning a process instead of thread is negligible, therefor using wp_remote_get with some special url to invoke additional "thread" is a very legitimate thing to do and avoid almost all the pitfalls associated with multithreading.

3
  • This is well explained. Thanks. I also just found out that support for pthreads to work with apache is being removed. In order to make pthreads work, it should be within a CLI evironment. For me, I need pthreads, but I wil postpone this solution till after the release (i.e., an enhancement). Also, I will need to setup WordPress as a CLI envornment (details here wp-cli.org ); doing so will allow me to work a pthreads/WordPress environment from CLI, alllowing me to do the heavy work at the backend without apache. Thaks again.
    – Greeso
    Dec 28 '15 at 0:55
  • Just to add, I will restrict pthreads to deal with non-db related issues. And as per your suggestion, use mutex for db writes.
    – Greeso
    Dec 28 '15 at 1:05
  • @Greeso, linux was designed to using multiple processes to handle concurrent execution needs, spawning a new process is really safer and as fast as using pthreads.. Dec 28 '15 at 3:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.