2
// "fcntl-linux.h" (with few lines skipped):
/* open/fcntl.  */
#define O_ACCMODE      0003
#define O_RDONLY         00
#define O_WRONLY         01
#define O_RDWR           02
#define O_APPEND      02000
#define O_NONBLOCK    04000
#define O_SYNC         04010000

Whenever a number is mentioned after '0', it becomes Octal representation. What is the reason for choosing less conventional "Octal" format over more popular decimal or hex?

Is this answer the correct way to make non-blocking to blocking socket?
Is there a difference between fcntl(socket, F_GETFL, 0) and fcntl(socket, F_GETFL)?

[Note: When I set the socket to non-blocking mode, the SSL connection doesn't work. In blocking mode it works fine. Hence, a code example describing the setting of modes will be good (if it's different from the linked code).]

Community
  • 1
  • 1
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 3
    They are more readable powers of 2 : 01, 02, 04, 010, 020, 040, etc. – Boiethios May 19 '16 at 14:29
  • Your calls to `fcntl` are identical, as [man says](http://linux.die.net/man/2/fcntl): **F_GETFL (void)** _Get the file access mode and the file status flags; arg is ignored._ – LPs May 19 '16 at 14:32
  • The linked answer works well. – LPs May 19 '16 at 14:39
  • 1
    You mean *octal*, not octet. During the prehistoric ages, i.e. when Unix was born, octal was far more popular than hexadecimal. (Writing the flags in decimal makes them completely incomprehensible, as decimal doesn't map very nicely onto bits.) – molbdnilo May 19 '16 at 14:40
  • Which is your question -- the use of octal constants, or how to make a socket non-blocking? Pick one. As for "convention", that's very much in the eye of the coder. He could've used `(1<<0)`, `(1<<1)` and `(1<<2)`, for example.... – DevSolar May 19 '16 at 14:53

2 Answers2

1

There's no real reason. They'd work just as well if they were in decimal; the computer doesn't care.

In general, "older" sets of flags are often defined in octal because they date back to an era when octal was more popular than hexadecimal. One might guess that the open flags were probably copied from some other OS that had them in octal.

  • 4.4BSD does have the fcntl/open flags in hexadecimal (and with different values)
  • System V has them in octal, but again with different values.
  • Minix, which provided significant inspiration and an early development environment for Linux, has them in octal and with the same values. They are, according to the comments, apparently assigned sequentially in the order of the relevant POSIX tables (except for O_RDONLY/O_WRONLY/O_RDWR, which are assigned their traditional values)
Random832
  • 37,415
  • 3
  • 44
  • 63
  • @iammilind I'm not sure what you mean by "correct". I might write it differently, but I can't see anything particularly wrong with it. What do you want to know about in particular? – Random832 May 19 '16 at 15:20
  • It will be good, if you can put the other 2 smaller questions in your answer. If you don't find the code wrong then mention it & also the difference between 2 calls. This will help the future visitors. – iammilind May 19 '16 at 15:24
  • @iammilind Technically, one possible issue with that code is that it doesn't check the result of F_GETFL for errors. – Random832 May 19 '16 at 15:24
  • @iammilind I don't understand why you want an analysis of an answer to another question to be posted as an answer to this question. That seems like a poor way to structure the site. Also, your SSL issue should probably be another question, whatever SSL library you are usingprobably has its own way to set the socket you are using to blocking mode or properly use non-blocking sockets. – Random832 May 19 '16 at 15:25
0

"Why fcntl() flag values are defined in Octal format"

As many of the users have suggested, it's purely because of historical reasons. Apparently Octal format was more popular than Hex format.

"Is this answer the correct way to make non-blocking to blocking socket?"

Yes. The answer is correct, as it serves the purpose of setting the flags with keeping various scenario in consideration. However, error checking would have been more helpful, which is trivial.

"Is there a difference between fcntl(socket, F_GETFL, 0) and fcntl(socket, F_GETFL)?"

No difference. The man page for fcntl(2) suggest the same.

F_GETFL (void) -- Get the file access mode and the file status flags; arg is ignored.

SSL connection with non-blocking socket

This is a little tricky part, where I was facing problem. A typical blocking call on SSL will look like this:

int result = ::SSL_connect(pSSL);  // <0: failed, 0: disconnected, 0<: pass

Now, the natural non-blocking alternative, we may assume as:

::fcntl(socketfd, F_SETFL, m_fcntl);
::connect(socketfd, ...);
int result == ::SSL_connect(pSSL);
// put the FD_SET() etc.
result = select(...);
if(result == 0)  ... // SSL timed out
else if(result < 0) ... // SSL error 
else ... // success

However, it doesn't work as simple as that. SSL is a bit complicated process, where messages are exchanged back and forth. Hence, we have to run ::SSL_Connect() in a loop to capture SSL_want_read, SSL_want_write. In a simplistic manner, the code may look like this:

::fcntl(socketfd, F_SETFL, m_fcntl);
::connect(socketfd, ...);
int result;  // looping for various handshakes & to/from messages
while((result = ::SSL_connect(pSSL)) < 0) {
  // put the FD_SET() etc.
  if(select(...) <= 0)
    break;
}
if(result == 0)  ... // SSL timed out
else if(result < 0) ... // SSL error 
else ... // success

I was able to fix my SSL issue with above (pseudo) code.

This answer is based on useful comments & my findings.

Community
  • 1
  • 1
iammilind
  • 68,093
  • 33
  • 169
  • 336