www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Program exiting from thread with infinite loop

reply Chris M. <chrismohrfeld comcast.net> writes:
I have the following that is supposed to pull and store info from 
a server every five minutes. It works if I move the body of 
deviceDownloader into main(). However when I try to spawn it in 
another thread it runs the function and then ends once it's done, 
like it's ignoring the while(true). I tried with std.parallelism, 
core.thread, vibe.d's concurrency library, but get the same 
result every time. Any idea how to better accomplish this?


import std.net.curl;
import device;
import std.datetime.systime;
impor std.concurrency;

void deviceDownloader()
{
     auto APIServer = HTTP();
     APIServer.addRequestHeader("X-Auth-Token:", AuthToken);
     APIServer.onProgress = delegate int(size_t dl, size_t dln, 
size_t ul, size_t uln)
     {
         if (dl != 0)
             write("Progress: downloaded ", dln, " of ", dl, "\r");

         return 0;
     };

     while (true)
     {
         auto currentTime = Clock.currTime;
         if (currentTime.minute % 5 == 0 && currentTime.second == 
0)
             retrieveDevices(URL, APIServer); // info retrieved 
and stored here
     }
}

void main()
{
     spawn(&deviceDownloader);
}
Jan 19 2018
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 19 January 2018 at 17:05:44 UTC, Chris M. wrote:
 However when I try to spawn it in another thread it runs the 
 function and then ends once it's done, like it's ignoring the 
 while(true).
It is probably terminating the child threads when the main one ends. Might help to have the main wait until the child dies too. But why are you putting it in a thread anyway? If the main is doing nothing than just waiting, might as well just keep the logic in there.
Jan 19 2018
parent reply Chris M. <chrismohrfeld comcast.net> writes:
On Friday, 19 January 2018 at 17:17:28 UTC, Adam D. Ruppe wrote:
 On Friday, 19 January 2018 at 17:05:44 UTC, Chris M. wrote:
 However when I try to spawn it in another thread it runs the 
 function and then ends once it's done, like it's ignoring the 
 while(true).
It is probably terminating the child threads when the main one ends. Might help to have the main wait until the child dies too.
I tried putting an infinite loop inside main() as well, didn't seem to help. I'm guessing there's probably a better way to make the main thread wait? I'm pretty new to threads and whatnot.
 But why are you putting it in a thread anyway? If the main is 
 doing nothing than just waiting, might as well just keep the 
 logic in there.
It'll be doing other things, this is just the first thing I've implemented.
Jan 19 2018
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/19/2018 09:46 AM, Chris M. wrote:

 I tried putting an infinite loop inside main() as well, didn't seem to
 help.
Another reason is an exception thrown in the child thread. If the exception is not caught, it will terminate the child thread and the main will not know anything about it. I have something about that here: http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency
 I'm guessing there's probably a better way to make the main thread
 wait?
std.core.thread_joinAll is a way but you would want to tell the other thread to terminate first. https://dlang.org/phobos/core_thread.html#.thread_joinAll So, instead of while(true), try while(someCondition). In that case the main thread sets the condition e.g. by sending a message and then joins. Ali
Jan 19 2018
parent reply Chris M. <chrismohrfeld comcast.net> writes:
On Friday, 19 January 2018 at 18:18:31 UTC, Ali Çehreli wrote:
 On 01/19/2018 09:46 AM, Chris M. wrote:

 I tried putting an infinite loop inside main() as well,
didn't seem to
 help.
Another reason is an exception thrown in the child thread. If the exception is not caught, it will terminate the child thread and the main will not know anything about it. I have something about that here: http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency
 I'm guessing there's probably a better way to make the main
thread
 wait?
std.core.thread_joinAll is a way but you would want to tell the other thread to terminate first. https://dlang.org/phobos/core_thread.html#.thread_joinAll So, instead of while(true), try while(someCondition). In that case the main thread sets the condition e.g. by sending a message and then joins. Ali
I'm not sure what's going on. I've tried all sorts of things from your link, it just runs the function once and exits every time. There aren't any exceptions being thrown from the thread. That robot example is basically exactly what I'm doing, and yet even that doesn't seem to resolve it.
Jan 19 2018
parent reply Chris M. <chrismohrfeld comcast.net> writes:
On Friday, 19 January 2018 at 20:35:14 UTC, Chris M. wrote:
 On Friday, 19 January 2018 at 18:18:31 UTC, Ali Çehreli wrote:
 On 01/19/2018 09:46 AM, Chris M. wrote:

 I tried putting an infinite loop inside main() as well,
didn't seem to
 help.
Another reason is an exception thrown in the child thread. If the exception is not caught, it will terminate the child thread and the main will not know anything about it. I have something about that here: http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency
 I'm guessing there's probably a better way to make the main
thread
 wait?
std.core.thread_joinAll is a way but you would want to tell the other thread to terminate first. https://dlang.org/phobos/core_thread.html#.thread_joinAll So, instead of while(true), try while(someCondition). In that case the main thread sets the condition e.g. by sending a message and then joins. Ali
I'm not sure what's going on. I've tried all sorts of things from your link, it just runs the function once and exits every time. There aren't any exceptions being thrown from the thread. That robot example is basically exactly what I'm doing, and yet even that doesn't seem to resolve it.
What I tried import std.net.curl; import device; import std.datetime.systime; impor std.concurrency; void deviceDownloader() { auto APIServer = HTTP(); APIServer.addRequestHeader("X-Auth-Token:", AuthToken); APIServer.onProgress = delegate int(size_t dl, size_t dln, size_t ul, size_t uln) { if (dl != 0) write("Progress: downloaded ", dln, " of ", dl, "\r"); return 0; }; while (true) { auto currentTime = Clock.currTime; if (currentTime.minute % 5 == 0 && currentTime.second == 0) retrieveDevices(URL, APIServer); // info retrieved and stored here ownerTid.send("tmp"); } } void main() { spawn(&deviceDownloader); while (true) { auto msg = receiveOnly!string(); } }
Jan 19 2018
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/19/2018 12:40 PM, Chris M. wrote:
 it just runs the function once and exits every time.
I would still put the following try+catch block around the whole logic: void deviceDownloader() { try { // ... existing contents of the function ... } catch (Exception exc) { writeln("Error: ", exc.msg); } catch (Error err) { writeln("Unrecoverable error: ", err.msg); } } Another thing to use it to start the program under a debugger and look at how many threads it has. If the program is called "deneme", on the console: gdb deneme Then, inside gdb: run Ctrl-C info threads That command lists two threads for me. Ali
Jan 19 2018
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/19/18 12:05 PM, Chris M. wrote:
 I have the following that is supposed to pull and store info from a 
 server every five minutes. It works if I move the body of 
 deviceDownloader into main(). However when I try to spawn it in another 
 thread it runs the function and then ends once it's done, like it's 
 ignoring the while(true). I tried with std.parallelism, core.thread, 
 vibe.d's concurrency library, but get the same result every time. Any 
 idea how to better accomplish this?
 
 
 import std.net.curl;
 import device;
 import std.datetime.systime;
 impor std.concurrency;
 
 void deviceDownloader()
 {
      auto APIServer = HTTP();
      APIServer.addRequestHeader("X-Auth-Token:", AuthToken);
      APIServer.onProgress = delegate int(size_t dl, size_t dln, size_t 
 ul, size_t uln)
      {
          if (dl != 0)
              write("Progress: downloaded ", dln, " of ", dl, "\r");
What is this call doing? You aren't importing std.stdio, so it can't be D's normal write call. -Steve
Jan 19 2018
parent reply Chris M. <chrismohrfeld comcast.net> writes:
On Friday, 19 January 2018 at 20:43:18 UTC, Steven Schveighoffer 
wrote:
 On 1/19/18 12:05 PM, Chris M. wrote:
 [...]
What is this call doing? You aren't importing std.stdio, so it can't be D's normal write call. -Steve
It is, left out the import on accident. I commented out the call to retrieveDevices, and now it's working, so at least I'm zoning in a bit. Appreciate all the help so far though.
Jan 19 2018
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/19/18 3:54 PM, Chris M. wrote:
 On Friday, 19 January 2018 at 20:43:18 UTC, Steven Schveighoffer wrote:
 On 1/19/18 12:05 PM, Chris M. wrote:
 [...]
What is this call doing? You aren't importing std.stdio, so it can't be D's normal write call. -Steve
It is, left out the import on accident. I commented out the call to retrieveDevices, and now it's working, so at least I'm zoning in a bit. Appreciate all the help so far though.
Hm... noticed you missed a 't' here as well: impor std.concurrency; It helps if you post actual working (or reproducing in any case) code. I've seen so many posts on this forum where people re-type their code in the post instead of copy-pasting, and then inadvertently leave out a major hint leading to the actual issue :) -Steve
Jan 19 2018
parent Chris M. <chrismohrfeld comcast.net> writes:
On Friday, 19 January 2018 at 21:01:51 UTC, Steven Schveighoffer 
wrote:
 On 1/19/18 3:54 PM, Chris M. wrote:
 On Friday, 19 January 2018 at 20:43:18 UTC, Steven 
 Schveighoffer wrote:
 On 1/19/18 12:05 PM, Chris M. wrote:
 [...]
What is this call doing? You aren't importing std.stdio, so it can't be D's normal write call. -Steve
It is, left out the import on accident. I commented out the call to retrieveDevices, and now it's working, so at least I'm zoning in a bit. Appreciate all the help so far though.
Hm... noticed you missed a 't' here as well: impor std.concurrency; It helps if you post actual working (or reproducing in any case) code. I've seen so many posts on this forum where people re-type their code in the post instead of copy-pasting, and then inadvertently leave out a major hint leading to the actual issue :) -Steve
Might have happened here. I left out two lines from main() that were for initializing a database because I didn't think they were relevant, then I realized the database was only being initialized in the main thread and not the one I was spawning. retrieveDevices() tried to access it and got a segfault (which I was ignoring because I was already getting a segfault from something else from before I put in threading). Should have been a red flag, but I moved the database initialization into the thread and it's working now.
Jan 19 2018