How can I have a new thread "take over" stdin? - c

In a program I am writing, I have a main thread that contains a loop for accepting console input. However, at some point a new thread is created that also tries to read from stdin. There is a variable that indicates that this other thread has started, but fgets is still waiting for input in the main thread, so the first console input entered after the new thread started is erroneously read by the main thread instead of the new thread.
Is there some way to solve this?
One thing I have tried is (in the main thread):
while(foo) {
if(busy) continue;
fgets(input,200,stdin);
if(busy) {
fputs(input,stdin);
} else {
// do whatever was supposed to be done with input intended for main thread
}
}
But I appear to have a misunderstanding of how streams work because the other fgets call does not read the data written via fputs.

Create a boolean variable protected an appropriate synchronization primitive. Initialize it to false. When a thread needs to ask a user a question and get an answer, wait for the variable to become 'false' (as appropriate for the synchronization primitive you chose) and then set it to true. Do all the output and get all the input you need. Then set the variable to 'false' and unblock any threads waiting (as appropriate for the synchronization primitive you chose).
For pthreads, a mutex and condition variable is probably best. For Windows, a critical section and auto reset event is probably best.
Your question does lack some details that may suggest a different answer. How is the user supposed to interact with a program when he can't be sure which of two separate code paths will get the input he types? If he types something and then hits 'enter', which code path it goes to would seem to depend on whether he hits 'enter' before the other thread is ready or not, which would seem to make an unusable program. In almost every realistic case, you will need to prompt the user and then wait for a response and then release input and output together.

For posterity, here is how I solved this.
Instead of having both threads be waiting for console input, I now have only one thread wait for input and delegate the handling of that input to functions specific to the program state.
The snippet above becomes:
while(foo) {
fgets(input,200,stdin);
if(busy) {
busyStuff(input);
} else {
nonBusyStuff(input);
}
}
and no other pthread that has an fgets call is ever created.

Related

Is it possible to change signal handler return point?

My first post here, so sorry if something not according to the rules.
Need advice for a problem in C.
I'm using a signal handler(SIGALRM) with timeout on an input from user (Stdin).
If the user didn't type anything then:
timeout expired
signal handler called
(PROBLEM) - > it returns to the same line before timeout occurred.
IMPORTANT :
I can't use select and can't use poll functions because it's a third party mechanism I use and must use their methods.
They eventually use select, but it's not straightforward and I just need to use their method.
The problem is:
After returning from signal handler i"m still 'stuck' on the same line waiting for input.
I can't use longjmp, can't call other method, can't print message to the user, can't use goto.
All unsafe from handler and creating errors.
The code looks something like this:
sa.sigaction(SIGALRM, &handler,Null):
.
.
While(done! =1)
{
alarm(20); //20 seconds timeout started
If(ReadLineMethod()>0) //wait for successful input from stdin
{
If(inputErr ==1)
{
**here(for example) I want to print user that timeout occured and return from the program (exit) **
}
alarm(0);
done==1;
// Do stuff here
}
}
/* Rest of the program before exit */
The while is for asking for a specific input until he types it right or timeout kicks him out.
void handler (int signum)
{
inputErr==1;// global parameter
}
Is there any work around for me to skip that line of reading the input after returning from the handler?
Or at least managing to print a proper message to the user that timeout occured?and not just return and get stuck on the input again lol.
Thanks a lot in advance.
Use a flag that the handler raises. Condition the printing with this flag. You will need to protect this flag with a mutex.
If you aren't allowed to reimplement ReadLineMethod() to be more reasonable, how about using threads? I'm not an expert on pthread, but you could probably set things up so that ReadLineMethod happens on one thread and polling for the error happens on another thread. There even seems to be a pthread_cancel function that can forcibly stop the reader thread if need be: http://man7.org/linux/man-pages/man3/pthread_cancel.3.html
Because you have so many restrictions, one way to get total control over this system will be:
Create a thread and run ReadLineMethod() in that thread.
Create another thread and use a timer in that thread. Do not use signals but detect otherwise that the rime has run out.
When the timer thread understands that the timer has run our, let it kill the thread in (1).
Else, if ReadLineMethod() has run to completion cleanly, let the timer thread do nothing and complete.
Of course, this is convoluted because of the requirements. If the fundamental requirement is known, there may be better alternatives.

C (linux) - Emulate / Skip scanf input

I have a program running 2 threads. The first is waiting for user input (using a scanf), the second is listening for some data over an udp socket. I would like to emulate user input to handle a specific notification with the first thread everytime I recive a specific udp packet. I know I can share variables between threads, so my question is: can I force the scanf to take input from a different thread? Can I skip the scanf in the first thread?
I believe scanf() by definition reads from stdin. Like you said, though, the different threads share memory so it's easy to pass information between them. Maybe have some shared variable and some sort of boolean value indicating whether or not the information has been updated from the thread reading from the network. It all depends on what you're specifically trying to do, but you may want to have some other mechanism for simulation that bypasses the scanf().
Since you've specifically mentioned Linux, I'm going to suggest a novelty here.
You can open (/proc/%d/fd/%d, getpid(), STDIN_FILENO) and write to it. This will actually open the input of the terminal. I wouldn't recommend this for a real program, but then again, scanf shouldn't be used in real programs either.

Writing and reading from terminal using pthreads

I want to create a multithreaded application in C using pthreads. I want to have a number of worker threads doing stuff in the background, but every once in a while, they will have to print something to the terminal so I suppose they will have to
"acquire the output device" (in this case stdout)
write to it
release the output device
rinse and repeat.
Also, I want the user to be able to "reply" to the output. For the sake of simplicity, I'm going to assume that nothing new will be written to the terminal until the user gives an answer to a thread's output, so that new lines are only written after the user replies, etc. I have read up on waiting for user input on the terminal, and it seems that ncurses is the way to go for this.
However, now I have read that ncurses is not thread-safe, and I'm unsure how to proceed. I suppose I could wrap everything terminal-related with mutexes, but before I do that I'd like to know if there's a smarter and possibly more convenient way of going about this, maybe a solution with condition variables? I'm somewhat lost here, so any help is welcome.
Why not just have a thread whose job is to interact with the terminal?
If other threads want to send message or get replies from the terminal, they can create a structure reflecting that request, acquire a mutex, and add that structure to a linked list if structures. The terminal thread will walk the linked list, outputting data as needed and getting replies as needed.
You can use a condition variable to signal the terminal thread that there's now data that needs to be output. The structure in the linked list can include a response condition variable that the terminal thread can signal when it has the reply, if any.
For output that gets no reply, the terminal thread can delete the structure after it outputs its contents. For output that gets a reply, the terminal thread can signal the thread that's interested in the output and then let that thread delete the structure once it has copied the output.
You can use fprintf on terminal. fprintf takes care of the concurrency issues, like it will use mutex locks on stdout before writing to the output device.

Exiting gracefully from a multithreaded process

I'm running a multi-threaded C program (process?) , making use of semaphores & pthreads. The threads keep interacting, blocking, waking & printing prompts on stdout continuously, without any human intervention. I want to be able to exit this process (gracefully after printing a message & putting down all threads, not via a crude CTRL+C SIGINT) by pressing a keyboard character like #.
What are my options for getting such an input from the user?
What more relevant information could I provide that will help to solve this problem?
Edit:
All your answers sound interesting, but my primary question remains. How do I get user input, when I don't know which thread is currently executing? Also, semaphore blocking using sem_wait() breaks if signalled via SIGINT, which may cause a deadlock.
There is no difference in reading standard input from threads except if more than one thread is trying to read it at the same time. Most likely your threads are not all calling functions to read standard input all the time, though.
If you regularly need to read input from the user you might want to have one thread that just reads this input and then sets flags or posts events to other threads based on this input.
If the kill character is the only thing you want or if this is just going to be used for debugging then what you probably want to do is occasionally poll for new data on standard input. You can do this either by setting up standard input as non-blocking and try to read from it occasionally. If reads return 0 characters read then no keys were pressed. This method has some problems, though. I've never used stdio.h functions on a FILE * after having set the underlying file descriptor (an int) to non-blocking, but suspect that they may act odd. You could avoid the use of the stdio functions and use read to avoid this. There is still an issue I read about once where the block/non-block flag could be changed by another process if you forked and exec-ed a new program that had access to a version of that file descriptor. I'm not sure if this is a problem on all systems. Nonblocking mode can be set or cleared with a 'fcntl' call.
But you could use one of the polling functions with a very small (0) timeout to see if there is data ready. The poll system call is probably the simplest, but there is also select. Various operating systems have other polling functions.
#include <poll.h>
...
/* return 0 if no data is available on stdin.
> 0 if there is data ready
< 0 if there is an error
*/
int poll_stdin(void) {
struct pollfd pfd = { .fd = 0, .events = POLLIN };
/* Since we only ask for POLLIN we assume that that was the only thing that
* the kernel would have put in pfd.revents */
return = poll(&pfd, 1, 0);
}
You can call this function within one of your threads until and as long as it retuns 0 you just keep on going. When it returns a positive number then you need to read a character from stdin to see what that was. Note that if you are using the stdio functions on stdin elsewhere there could actually be other characters already buffered up in front of the new character. poll tells you that the operating system has something new for you, not what C's stdio has.
If you are regularly reading from standard input in other threads then things just get messy. I'm assuming you aren't doing that (because if you are and it works correctly you probably wouldn't be asking this question).
You would have a thread listening for keyboard input, and then it would join() the other threads when receiving # as input.
Another way is to trap SIGINT and use it to handle the shutdown of your application.
The way I would do it is to keep a global int "should_die" or something, whose range is 0 or 1, and another global int "died," which keeps track of the number of threads terminated. should_die and died are both initially zero. You'll also need two semaphores to provide mutex around the globals.
At a certain point, a thread checks the should_die variable (after acquiring the mutex, of course). If it should die, it acquires the died_mutex, ups the died count, releases the died_mutex, and dies.
The main initial thread periodically wakes up, checks that the number of threads that have died is less than the number of threads, and goes back to sleep. The main thread dies when all the other threads have checked in.
If the main thread doesn't spawn all the threads itself, a small modification would be to have "threads_alive" instead of "died". threads_alive is incremented when a thread forks, and decremented when the thread dies.
In general, terminating a multithreaded operation cleanly is a pain in the butt, and besides special cases where you can use things like the semaphore barrier design pattern, this is the best I've heard of. I'd love to hear it if you find a better, cleaner one.
~anjruu
In general, I have threads waiting on a set of events and one of those events is the termination event.
In the main thread, when I have triggered the termination event, I then wait on all the threads having exited.
SIGINT is actually not that difficult to handle and is often used for graceful termination. You need a signal handler and a way to tell all the threads that it's time to stop. One global flag that threads check in their loops and the signal handler sets might do. Same approach works for "on user command" termination, though you need a way to get the input from the terminal - either poll in a dedicated thread, or again, set the terminal to generate a signal for you.
The tricky part is to unblock waiting threads. You have to carefully design the notification protocol of who tells who to stop and what they need to do - put dummy message into a queue, set a flag and signal a cv, etc.

Threads in userspace and yield

I am supposed to implement a userlevel threads library in C. To do so, I need to implement yield(), createThread() and destroyThread() functions. I believe I've got the basics right:
To keep track of threads, I'll use a queue of ThreadControlBlock elements (which resemble PCBs in an OS) that look like this:
struct ThreadControlBlock {
int ThreadId,
u_context *context };
We can use the setcontext() family of functions to "save" and "load" the context.
Upon initialization of the program, initialize ThreadQueue with no elements.
Now the part I am not getting: when a thread calls yield(), I get the current context and save it in a ThreadControlBlock and put in the queue. Then get the first element in the queue and load the context in it, and execution proceeds.
The question is, if I do this, say I am a thread calling yield() and the next thread is myself. If I am saving the context and loading it again, upon re-entering wouldn't I be at the exact same spot where I was (before calling yield()?) And this would keep going on forever?
When a thread calls yield(), you have to save the state of a thread that's about to return from a yield() call. Don't save the context from immediately before the yield().
The same issue actually applies if you're switching to another task, too - since that other task saved its context at the same point (where it was about to switch to a second task). Using setcontext() and getcontext(), you need to use a static variable to keep track of whether you're switching in or switching out:
static volatile int switched;
switched = 0;
getcontext(current->context);
if (!switched)
{
switched = 1;
setcontext(next->context);
}
Alternatively, you can just use swapcontext(current->context, next->context);
It's perfectly reasonable in your yield() implementation to check to see if the next thread is the current thread and treat that case as a no-op.
If there are no other threads to run besides the current thread then there is nothing else to do besides just return from yield. I wouldn't bother with calling swapcontext in this case, though -- just detect and return.
I think that what you are actually dealing with is what to do when no threads (including the current one) when yield is called. An easy way to deal with this is to have an idle thread, which is only run when the run queue (ready threads) is empty. This thread will probably just:
{
while (1) {
yield();
pause();
}
}
This allows your program to go to sleep (via pause) until a signal happens. Hopefully the signal will be some event that makes one of the other threads ready to run, so the next call to yield will run the other thread instead of running the idle thread again.

Resources