4

I have a C program with two threads one of those threads is almost all the time blocked in a fgets() waiting for user input. The second thread may need to print to the terminal while the first one is blocked on fgets().

From my tests it seems that the program waits for the fgets() on the first thread to return and then the second thread can print.

Is this who it works or could I print while the the other thread is blocked on the fgets()?

This implementations runs on eCos (embedded Configurable operating system).

Thread locked on fgets():

int my_getline (char** argv, int argvsize)
{
    static char line[MAX_LINE];
    char *p;
    int argc;

    fgets(line, MAX_LINE, stdin);


    for (argc=0,p=line; (*line != '\0') && (argc < argvsize); p=NULL,argc++) {
        p = strtok(p, " \t\n");
        argv[argc] = p;
        if (p == NULL) return argc;
    }
    argv[argc] = p;
    return argc;
}

Thread trying to print:

while(1){
        unsigned char bufr[50];
        read_until(bufr);
        if (bufr[1] == (unsigned char)NMFL ){
            cyg_mutex_lock(&scree_mtx);
            printf("Memory half full!\n");
            cyg_mutex_unlock(&scree_mtx);
            continue;
        }
        cyg_mbox_put( mbx_serial_userH, bufr );     
}

Output (I'm sure the message was there before):

Output

Sebastião
  • 160
  • 13
  • One thread waiting on input should not block another thread that's trying to write to output. – Oliver Charlesworth Dec 11 '18 at 20:55
  • 1
    Does your output end with `\n`? `stdout` is line-buffered, so it's not flushed until you print a newline. – Barmar Dec 11 '18 at 20:56
  • Yes the ```printf()```ends with ```\n``` @Barmar – Sebastião Dec 11 '18 at 20:59
  • With the edits, the question does not make sense. The output shown does not seem to have anything to do with the source that's been added. – R.. GitHub STOP HELPING ICE Dec 11 '18 at 21:10
  • As I noted above, there is a deep question about interaction between locking on different files with buffered stdio, but it usually happens in the opposite direction (where a writer is waiting, not a reader), and with the source shown so far there does not seem to be any evidence that this type of issue is at fault. – R.. GitHub STOP HELPING ICE Dec 11 '18 at 21:11
  • @R.. The vote isn't mine, but given there was originally no code or context in the question, I can see why someone voted like this. – Oliver Charlesworth Dec 11 '18 at 21:21
  • It's not clear to me what the relevance of that output snippet is. Also, what is `read_until`? – Oliver Charlesworth Dec 11 '18 at 21:26
  • What is the *value* of `stdin` and `stdout` - the actual value of the pointer itself? Maybe they're the same `FILE *`? And does Windows - or whatever your platform is - have [`flockfile()`/`funlockfile()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/flockfile.html)? If so, instead of using `fgets()` to read from `stdin()`, just call `flockfile( stdin )`, block on something not `FILE *`- or IO-related, and see if `stdout` blocks. – Andrew Henle Dec 11 '18 at 21:27
  • ```read_until()``` is a function to read from a serial until it gets 0xFE. – Sebastião Dec 11 '18 at 21:27
  • 1
    I guess what I'm getting at is - it's very unclear from those code snippets and output snippet how you've concluded that it's blocked trying to output. Can you provide something closer to a [minimal test case](https://stackoverflow.com/help/mcve)? – Oliver Charlesworth Dec 11 '18 at 21:32
  • Suggest `if (fgets(line, MAX_LINE, stdin) == NULL) Handle_That()` to set aside unexpected input concerns. AFAIK, `line` has random junk in at `*line ...` and causes UB. – chux - Reinstate Monica Dec 11 '18 at 21:36
  • Are you calling `cyg_mutex_lock(&scree_mtx);` before `my_getline`, by any chance? – user253751 Dec 11 '18 at 21:51
  • @OliverCharlesworth: That's still not off-topic. It could be "very low quality". – R.. GitHub STOP HELPING ICE Dec 11 '18 at 22:02
  • @R.. Whether the "must include the desired behavior, a specific problem or error and the shortest code necessary" option is semantically "off topic" is of course debatable ;) – Oliver Charlesworth Dec 11 '18 at 22:04
  • @immibis no I'm not... – Sebastião Dec 11 '18 at 22:35
  • sorry, but `cyg_mutex_lock` is top suspicious as the candidate of the lock, rather than printf. You need to post following the guidelines of [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) Please, edit the question and include such a sample code. – Luis Colorado Dec 13 '18 at 10:10
  • The problem is solved it had to do with thread priority and the odd way eCos scheduler works. Changing priorities and adding some semaphores solved it. Regarding the example this a reader complex software, that’s why the question didn’t include an example in first place. – Sebastião Dec 13 '18 at 20:57

1 Answers1

2

The C standard does not specify any association at all between the standard input stream and the standard output stream. In particular, it does not specify that one thread blocking on reading from standard input, via any standard function, should cause any output function to block.

HOWEVER, the standard also does not say the opposite, that a thread blocking on input input from stdin must not cause another to block on output to stdout. Whether that happens would be a function of the C implementation, and probably of the specific devices with which stdin and stdout are associated.

You appear to be using a Windows C implementation with stdin and stdout both connected to a CMD.EXE window. Windows has a lot of idiosynchrasies, and I'm inclined to guess that the blocking you observe is one of them. I would not expect the same on Linux or OSX, but that does not mean it is erroneous.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Actually this is an implementation for eCos (embedded Configurable operating system), there may be the case that this is the way eCos works... – Sebastião Dec 11 '18 at 21:22
  • 2
    This does not seem to really answer the question. This is more of a comment about the C standard and really saying that this observed behavior is not something required by the C Standard and is probably to do with the underlying I/O subsystem implementation of the OS or how the C I/O libraries implemented the I/O functionality. It appears from this documentation there are at least two configurations for the C library of eCos to be or not to be thread safe. http://ecos.sourceware.org/docs-latest/user-guide/sample-twothreads.html however it is unclear as to the behavior of thread safe. – Richard Chambers Dec 11 '18 at 22:00
  • I don't think the standard implicitly permits an implementation that does not allow forward progress in situations where the abstract machine as specified would make forward progress. It does make some (outdated and harmful) allowances for flushing output streams when requesting input, which has nasty deadlock implications if an implementation chooses to take that allowance, and I originally thought that was relevant to this question, but on further consideration it seems not to be. – R.. GitHub STOP HELPING ICE Dec 11 '18 at 22:05
  • 1
    @RichardChambers, after I wrote this answer, the question was edited to specify eCos, apparently in response. The original version, to which this responds, was an unspecific "is this how it works?", to which "it depends, C itself does not specify" is about as responsive as one can be. – John Bollinger Dec 11 '18 at 22:09
  • @JohnBollinger there is really too much missing from the posted question to provide a reasonably good answer. eCos seems to have a fairly standard roller coaster proprietary and open source history and since its embedded there may be hardware related considerations. No mention in the posted question of the context/environment. Is this a simulator for instance? It just not really a good question as it is lacking so much including a minimal and verifiable program. Any answer is just throwing something at the wall until the question is redone to a more acceptable standard. – Richard Chambers Dec 11 '18 at 22:19