0

I'm connecting to a TCP socket, nonblockingly. printf("%m") prints out Operation now in progress yet errno is set to 0. I save errno's value before printing too, to make sure printf doesn't fiddle with it. It's weird - printf should output Success. I mean obviously the problem is that when I access errno I get 0. I'm using uclibc on a pretty old kernel (Around 2.6), if that matters. I can't really find any difference between how vsprintf accesses errno vs me accessing *__errno_location().

Alternatively, how could I tell if my socket had an actual issue with connect or if it's just still connecting?

Example:

int sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);

/* create sockaddr struct (remote)... */

int fd = connect(sock, (const struct sockaddr*)&remote, sizeof(remote));

printf("%d, %d\n", fd, errno);
printf("%m");

Outputs:

-1, 0
Operation now in progress

I'd expect the following output:

-1, 115
Operation now in progress

As 115 is EINPROGRESS

  • What is the actual `errno`? What does `strerror(0)` return? – tadman Sep 09 '20 at 08:40
  • `errno` is 0, `strerror(0)` is `Success` – dobabeh362 Sep 09 '20 at 09:20
  • 1
    `Operation now in progress` corresponds to `EINPROGRESS`. – Ian Abbott Sep 09 '20 at 09:47
  • Yeah. I know. But when I check `errno`'s value I get `0`. I don't get `150` which is `EINPROGRESS`. Yet right after that `printf("%m")` outputs `Operation now in progress`. Which is the problem – dobabeh362 Sep 09 '20 at 10:17
  • 3
    Please show the code, preferable a [mre]. Otherwise we do not know how exactly `errno` is set or checked. Did you try to write `errno` and read `*__errno_location()` or vice versa? – Bodo Sep 09 '20 at 10:49
  • Added an example. Hope it suffices – dobabeh362 Sep 09 '20 at 12:06
  • The code is flawed - `printf` may set errno to `115`, resulting in subsequent `printf` in printing the errno. It may also happen that `printf` happens to set errno to 115 before executing `%m`. Please maybe try `int fd = connect(...); int sav = errno; printf("%m %d %d\n", fd, errno);`. Please post an [MCVE] and if `%m` _extension_ is not working, then try the standard `strerror`. – KamilCuk Sep 09 '20 at 12:17
  • Thanks for your reply. I have indeed tried saving the value inbetween the `printf` and `connect`. It seems as if `%m` accesses a different `errno`. But from the research I've done - it should access the very same value, obviously. – dobabeh362 Sep 09 '20 at 13:50
  • Also - why would `printf` set errno to `EINPROGRESS`? I mean it _could_, but why would it – dobabeh362 Sep 09 '20 at 14:16
  • 3
    It might sound silly, but I'd verify that you don't have something shadowing `errno` in your scope (because that sounds to me like the most reasonable explanation). This could be anything from a macro to a difference between how your code and the library handle thread local storage (e.g. library built without threads configured, you're bulit with threads configured, or vice versa) – Hasturkun Sep 09 '20 at 14:56
  • @Hasturkun Besides setting a watchpoint on errno's address with GDB, what else could I do? – dobabeh362 Sep 10 '20 at 10:25
  • A watchpoint probably won't help in this case, because it sounds like your errno and the library's aren't the same one. You can check a disassembly to see how you're getting at errno (or preprocessor output for some cases) and compare it to something from the library. Searching for "uclibc errno" brings up some bugs that sound related (e.g. [this](http://uclibc.10924.n7.nabble.com/PATCH-fix-errno-location-for-non-TLS-case-tp2684.html)). I don't know what uclibc version you're on, so don't know if you're affected by one of these. – Hasturkun Sep 10 '20 at 11:47

0 Answers0