Re: Where can I find out rules on blocking in threads?
1. initializes some UI goo (but doesn't start any of it UP) using a GUI framework (Qt) 2. creates a FIFO, and then spawns a thread 3. this new thread then does: fifo = open(fifoPath, O_RDONLY); ... Now, the problem is that when step 3 above blocks on the open(2) call (as it should, since the other end of the pipe isn't opened yet), the whole application is frozen, and the main thread can't continue with GUI processing, and the app appears to die. What is goofy is that this works just fine under Linux. So, FreeBSD has slightly different blocking rules or something -- but I don't understand them. It also hangs under Solaris 8/Intel. So, the question is: how can I find out what these differences are and try to get around them. I'm using this to limit instances of my program to one, and need a named pipe instead of just a lock file so that new instances can communicate any arguments they might have been given, etc ... I think the FreeBSD behavior is wrong, the spec says that when opening a FIFO with O_NONBLOCK clear that: An open() for reading-only shall block the calling thread until a thread opens the file for writing. An open() for writing-only shall block the calling thread until a thread opens the file for reading. The FBSD man pages will let you know if something will block or not, for example, look at the "implementation notes" section for open. You can open the fifo non-blocking and then clear O_NONBLOCK using fcntl, hopefully that will work in all environments. Peter -- Peter Dufault ([EMAIL PROTECTED]) Realtime development, Machine control, HD Associates, Inc. Fail-Safe systems, Agency approval To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
At 17:21 26/02/01 -0800, Marc W wrote: hello! I'm running into a problem with some threading using pthreads in an application i'm writing for FreeBSD. The application basically 1. initializes some UI goo (but doesn't start any of it UP) using a GUI framework (Qt) 2. creates a FIFO, and then spawns a thread 3. this new thread then does: fifo = open(fifoPath, O_RDONLY); 4. after the new thread is spawned, the application is supposed to then continue initialization, showing the main window and continuing on happily. Now, the problem is that when step 3 above blocks on the open(2) call (as it should, since the other end of the pipe isn't opened yet), the whole application is frozen, and the main thread can't continue with GUI processing, and the app appears to die. What is goofy is that this works just fine under Linux. So, FreeBSD has slightly different blocking rules or something -- but I don't understand them. It also hangs under Solaris 8/Intel. So, the question is: how can I find out what these differences are and try to get around them. I'm using this to limit instances of my program to one, and need a named pipe instead of just a lock file so that new instances can communicate any arguments they might have been given, etc ... any suggestions? depens on how long it blocks? is it indefinitely blocking or for some time? in the latter, you might use a sleep() in the child before the open(). Does the parent wait for its child (the thread that does the open fifo thing)? can you provided a small piece of code that shows this behaviour? cheers, mouss To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
can you provided a small piece of code that shows this behaviour? Here's one without error checking. Be sure to use -pthread. Peter -- Peter Dufault ([EMAIL PROTECTED]) Realtime development, Machine control, HD Associates, Inc. Fail-Safe systems, Agency approval #include unistd.h #include sys/stat.h #include sys/types.h #include fcntl.h #include pthread.h #include stdio.h struct threadstuff { int rfid, wfid; const char *name; }; static void * reader(void *arg) { struct threadstuff *pts = (struct threadstuff *)arg; fprintf(stderr, "Opening %s for read...", pts-name); pts-rfid = open(pts-name, O_RDONLY); fprintf(stderr, " reader got fid %d.\n", pts-rfid); return 0; } static void * writer(void *arg) { struct threadstuff *pts = (struct threadstuff *)arg; fprintf(stderr, "Opening %s for write...", pts-name); pts-wfid = open(pts-name, O_WRONLY); fprintf(stderr, " writer got fid %d.\n", pts-wfid); return 0; } int main(int ac, char *av[]) { pthread_t r, w; void *value; struct threadstuff ts; ts.name = "./my_fifo"; ts.rfid = ts.wfid = -1; (void)unlink(ts.name); (void)mkfifo(ts.name, 0666); pthread_create(r, 0, reader, (void *)ts); pthread_create(w, 0, writer, (void *)ts); pthread_join(r, value); pthread_join(w, value); if (ts.rfid != -1) (void)close(ts.rfid); if (ts.wfid != -1) (void)close(ts.wfid); return 0; } To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
Is this a library issue in libc_r? I just wrote a quick test program using rfork(RFMEM|RFPROC) to create a child thread. I then had both the parent and the child attempt to open the pre-existing file /tmp/blah with O_EXLOCK set. When I specify O_NONBLOCK, the child open() fails immediately. When I do not specify O_NONBLOCK, the child blocks indefinitely: #if TRY_NONBLOCKING # define O_ (O_NONBLOCK) #else # define O_ (0) #endif int main(int argc, char* *argv) { thread_creation_using_rfork(RFPROC|RFTHREAD) ; /* parent continues here */ printf("main: %d\n", open("/tmp/blah", O_RDWR|O_EXLOCK|O_)) ; for( ; ; ) ; } void childthreadproc(void *) { /* child begins here */ /* fails for O_NONBLOCK, otherwise blocks indefinitely */ printf("child: %d\n", open("/tmp/blah", O_RDWR|O_EXLOCK|O_)) ; for( ; ; ) ; } Note that I've omitted the guts of rfork(). Therefore, it seems to me that the blocking is at the library level, not the kernel level. Have I missed something? Eddy --- Brotsman Dreger, Inc. EverQuick Internet / EternalCommerce Division E-Mail: [EMAIL PROTECTED] Phone: (316) 794-8922 --- To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
Date: Tue, 27 Feb 2001 15:15:33 + (GMT) From: E.B. Dreger [EMAIL PROTECTED] Is this a library issue in libc_r? I just wrote a quick test program using rfork(RFMEM|RFPROC) to create a child thread. Correction: RFTHREAD|RFPROC Sorry... I have RFMEM on the brain. The pseudocode gave the correct RFXXX flags. (I also typed "#if" instead of "#ifdef". FreeBSD multitasks better than I do this morning.) FWIW, does anyone know what Linuxthread's blocking behavior is? The original poster mentioned that Linux gave the desired behavior... what about the Linuxthreads library? Although I have written pthread applications, I prefer to do my thread programming at a lower level; hence my use of rfork(). Hopefully the info will be useful, though. Eddy --- Brotsman Dreger, Inc. EverQuick Internet / EternalCommerce Division E-Mail: [EMAIL PROTECTED] Phone: (316) 794-8922 --- To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
I think the FreeBSD behavior is wrong, the spec says that when opening a FIFO with O_NONBLOCK clear that: An open() for reading-only shall block the calling thread until a thread opens the file for writing. An open() for writing-only shall block the calling thread until a thread opens the file for reading. The FBSD man pages will let you know if something will block or not, for example, look at the "implementation notes" section for open. You can open the fifo non-blocking and then clear O_NONBLOCK using fcntl, hopefully that will work in all environments. I have tried this, but it gets even weirder then: - the call to open always succeeds right away (even when there are no threads on the write end of the fifo) - the immediately following call to read() also succeeds, returning 0 bytes as the number of bytes read. it gets worse -- when i change my loop to be: while (1) { fifo = open(fifoPath, O_RDONLY | O_NONBLOCK); cread = read(fifo, buf, sizeof(buf)); if (cread 0) do_something(); close(fifo); usleep(10); } anybody who tries to open the write end of the fifo ends up hanging .. argh! i'll keep investigating... my poor "2 hour solution to single instancing" is going into day 3 :-) marc. To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
It seems ther's a problem here:) the manpage of open states " disables thread rescheduling...". Is this the explanation? As far as I can tell, Posix requires that some function should not block the process, and lists open(), fcntl(), ... Are there any pthread gurus who could give us the real truth here? cheers, mouss To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
it gets worse -- when i change my loop to be: while (1) { fifo = open(fifoPath, O_RDONLY | O_NONBLOCK); cread = read(fifo, buf, sizeof(buf)); if (cread 0) do_something(); close(fifo); usleep(10); } anybody who tries to open the write end of the fifo ends up hanging .. It's a little messier than I hoped. As long as no one has opened the FIFO for write read returns a zero with errno clear. If you don't have time slicing turned on for the threads you'll hang forever. You'll have to do something like this: #include unistd.h #include sys/stat.h #include sys/types.h #include errno.h #include fcntl.h #include pthread.h #include stdio.h struct threadstuff { int rfid, wfid; const char *name; }; static void * reader(void *arg) { int flags; ssize_t r; char buff[32]; int cr; struct threadstuff *pts = (struct threadstuff *)arg; fprintf(stderr, "Opening %s for read, non-blocking...\n", pts-name); pts-rfid = open(pts-name, O_RDONLY | O_NONBLOCK); fprintf(stderr, "reader got fid %d, setting to blocking...\n", pts-rfid); (void)fcntl(pts-rfid, F_GETFL, flags); flags = ~O_NONBLOCK; (void)fcntl(pts-rfid, F_SETFL, flags); fprintf(stderr, "Trying to read something from the FIFO...\n"); cr = 0; /* * You better have round robin turned on here or be sure * the writer is of higher priority or you'll just buzz * away the CPU. */ do { errno = 0; r = read(pts-rfid, buff, sizeof(buff) - 1); if (errno == 0 r == 0) { /* No one has the FIFO open for write. * You should delay here (or preferably synchronize) * to avoid busy waiting. */ cr++; fprintf(stderr, "%s(%3d) No writer yet.\r", ((cr % 5) == 1) ? "\n" : "", cr); } } while (r == 0); if (r 0) { perror("Read of FIFO"); } else { buff[r] = 0; fprintf(stderr, "Read \"%s\".\n", buff); } return 0; } static void * writer(void *arg) { char something[] = "Something"; struct threadstuff *pts = (struct threadstuff *)arg; fprintf(stderr, "Opening %s for write\n", pts-name); pts-wfid = open(pts-name, O_WRONLY); fprintf(stderr, "writer got fid %d.\n", pts-wfid); write(pts-wfid, something, sizeof(something)); return 0; } int main(int ac, char *av[]) { pthread_t r, w; void *value; struct threadstuff ts; ts.name = "./my_fifo"; ts.rfid = ts.wfid = -1; (void)unlink(ts.name); (void)mkfifo(ts.name, 0666); pthread_create(r, 0, reader, (void *)ts); pthread_create(w, 0, writer, (void *)ts); pthread_join(r, value); pthread_join(w, value); if (ts.rfid != -1) (void)close(ts.rfid); if (ts.wfid != -1) (void)close(ts.wfid); return 0; } To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
just did some more testing -- the problem does appear to be FreeBSD specific. Solaris 8 and all the Linuxes I've got handy run this no probs. Don't have any openbsd or netbsd to test those out ... I'll just #ifdef in some code for FreeBSD. anybody know what #ifdef I should use before I start digging through headers? thanks :-) marc. - From: mouss [EMAIL PROTECTED] To: Peter Dufault [EMAIL PROTECTED] Cc: Marc W [EMAIL PROTECTED], [EMAIL PROTECTED] Subject: Re: Where can I find out rules on blocking in threads? Sent: 02/27/01 22:04 It seems ther's a problem here:) the manpage of open states " disables thread rescheduling...". Is this the explanation? As far as I can tell, Posix requires that some function should not block the process, and lists open(), fcntl(), ... Are there any pthread gurus who could give us the real truth here? cheers, mouss To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message
Re: Where can I find out rules on blocking in threads?
Well, my understand (limited) of *BSD's threading systems is that they are not truly pre-emptive -- they use a scheme similar to PTH for forcing a single process to jump around its process space. Given this, it doesn't suprise me that a few system calls don't yield; possibly because they aren't wrapped properly; or maybe can't be wrapped. Of course, this is based on my _very_ limited knowledge... :) D. On Tue, Feb 27, 2001 at 01:43:41PM -0800, Marc W wrote: just did some more testing -- the problem does appear to be FreeBSD specific. Solaris 8 and all the Linuxes I've got handy run this no probs. Don't have any openbsd or netbsd to test those out ... I'll just #ifdef in some code for FreeBSD. anybody know what #ifdef I should use before I start digging through headers? thanks :-) marc. - From: mouss [EMAIL PROTECTED] To: Peter Dufault [EMAIL PROTECTED] Cc: Marc W [EMAIL PROTECTED], [EMAIL PROTECTED] Subject: Re: Where can I find out rules on blocking in threads? Sent: 02/27/01 22:04 It seems ther's a problem here:) the manpage of open states " disables thread rescheduling...". Is this the explanation? As far as I can tell, Posix requires that some function should not block the process, and lists open(), fcntl(), ... Are there any pthread gurus who could give us the real truth here? cheers, mouss To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message