libposix: add support for O_NONBLOCK
We keep a list of non blocking fds and use awake to make them not block on read, write, pread and pwrite.
This commit is contained in:
parent
96f5c08548
commit
ea21d3cd2d
|
@ -0,0 +1,110 @@
|
||||||
|
// C program to illustrate
|
||||||
|
// non I/O blocking calls
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h> // library for fcntl function
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define MSGSIZE 6
|
||||||
|
char* msg1 ="hello";
|
||||||
|
char* msg2 ="bye !!";
|
||||||
|
|
||||||
|
void parent_read(int p[])
|
||||||
|
{
|
||||||
|
int nread;
|
||||||
|
char buf[MSGSIZE];
|
||||||
|
|
||||||
|
// write link
|
||||||
|
close(p[1]);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
// read call if return -1 then pipe is
|
||||||
|
// empty because of fcntl
|
||||||
|
nread = read(p[0], buf, MSGSIZE);
|
||||||
|
switch (nread) {
|
||||||
|
case -1:
|
||||||
|
|
||||||
|
// case -1 means pipe is empty and errono
|
||||||
|
// set EAGAIN
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
printf("(pipe empty)\n");
|
||||||
|
sleep(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
perror("read");
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// case 0 means all bytes are read and EOF(end of conv.)
|
||||||
|
case 0:
|
||||||
|
printf("End of conversation\n");
|
||||||
|
|
||||||
|
// read link
|
||||||
|
close(p[0]);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
|
||||||
|
// text read
|
||||||
|
// by default return no. of bytes
|
||||||
|
// which read call read at that time
|
||||||
|
printf("MSG = %s\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void child_write(int p[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// read link
|
||||||
|
close(p[0]);
|
||||||
|
|
||||||
|
// write 3 times "hello" in 3 second interval
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
write(p[1], msg1, MSGSIZE);
|
||||||
|
sleep(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write "bye" one times
|
||||||
|
write(p[1], msg2, MSGSIZE);
|
||||||
|
|
||||||
|
// here after write all bytes then write end
|
||||||
|
// doesn't close so read end block but
|
||||||
|
// because of fcntl block doesn't happen..
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int p[2];
|
||||||
|
|
||||||
|
// error checking for pipe
|
||||||
|
if (pipe(p) < 0)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
// error checking for fcntl
|
||||||
|
if (fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
|
||||||
|
exit(2);
|
||||||
|
|
||||||
|
// continued
|
||||||
|
switch (fork()) {
|
||||||
|
|
||||||
|
// error
|
||||||
|
case -1:
|
||||||
|
exit(3);
|
||||||
|
|
||||||
|
// 0 for child process
|
||||||
|
case 0:
|
||||||
|
child_write(p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
parent_read(p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -45,6 +45,7 @@
|
||||||
"101-files.c",
|
"101-files.c",
|
||||||
"102-files.c",
|
"102-files.c",
|
||||||
"103-files.c",
|
"103-files.c",
|
||||||
|
"104-files-nonblocking.c",
|
||||||
"120-fcntl.c",
|
"120-fcntl.c",
|
||||||
"121-fcntl.c",
|
"121-fcntl.c",
|
||||||
"200-signals.c",
|
"200-signals.c",
|
||||||
|
@ -112,6 +113,7 @@
|
||||||
"101-files.c",
|
"101-files.c",
|
||||||
"102-files.c",
|
"102-files.c",
|
||||||
"103-files.c",
|
"103-files.c",
|
||||||
|
"104-files-nonblocking.c",
|
||||||
"120-fcntl.c",
|
"120-fcntl.c",
|
||||||
"121-fcntl.c",
|
"121-fcntl.c",
|
||||||
"200-signals.c",
|
"200-signals.c",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of Jehanne.
|
* This file is part of Jehanne.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
|
* Copyright (C) 2017-2018 Giacomo Tesio <giacomo@tesio.it>
|
||||||
*
|
*
|
||||||
* This is free software: you can redistribute it and/or modify
|
* This is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -375,6 +375,9 @@ extern int libposix_translate_error(PosixErrorTranslator translation, uintptr_t
|
||||||
/* define the value of AT_FDCWD according to the library headers */
|
/* define the value of AT_FDCWD according to the library headers */
|
||||||
extern int libposix_define_at_fdcwd(int AT_FDCWD);
|
extern int libposix_define_at_fdcwd(int AT_FDCWD);
|
||||||
|
|
||||||
|
/* define the value of O_NONBLOCK according to the library headers */
|
||||||
|
extern int libposix_define_ononblock(int O_NONBLOCK);
|
||||||
|
|
||||||
/* define the value of a specific PosixError according to the library headers */
|
/* define the value of a specific PosixError according to the library headers */
|
||||||
extern int libposix_define_errno(PosixError e, int errno);
|
extern int libposix_define_errno(PosixError e, int errno);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of Jehanne.
|
* This file is part of Jehanne.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
|
* Copyright (C) 2017-2018 Giacomo Tesio <giacomo@tesio.it>
|
||||||
*
|
*
|
||||||
* This is free software: you can redistribute it and/or modify
|
* This is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -21,6 +21,8 @@
|
||||||
#include <posix.h>
|
#include <posix.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
extern int __libposix_O_NONBLOCK;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fcntl_dup(int *errnop, int fd, int minfd)
|
fcntl_dup(int *errnop, int fd, int minfd)
|
||||||
{
|
{
|
||||||
|
@ -150,8 +152,9 @@ POSIX_fcntl(int *errnop, int fd, PosixFDCmds cmd, uintptr_t arg)
|
||||||
return -1;
|
return -1;
|
||||||
return flags & (~OCEXEC);
|
return flags & (~OCEXEC);
|
||||||
case PosixFDCSetFL:
|
case PosixFDCSetFL:
|
||||||
|
flags = (int)arg;
|
||||||
|
__libposix_set_non_blocking(fd, flags & __libposix_O_NONBLOCK);
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*errnop = __libposix_get_errno(PosixEINVAL);
|
*errnop = __libposix_get_errno(PosixEINVAL);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of Jehanne.
|
* This file is part of Jehanne.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
|
* Copyright (C) 2017-2018 Giacomo Tesio <giacomo@tesio.it>
|
||||||
*
|
*
|
||||||
* This is free software: you can redistribute it and/or modify
|
* This is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -33,6 +33,11 @@ static int *__libposix_coe_fds;
|
||||||
static int __libposix_coe_fds_size;
|
static int __libposix_coe_fds_size;
|
||||||
static int __libposix_coe_fds_used;
|
static int __libposix_coe_fds_used;
|
||||||
|
|
||||||
|
int __libposix_O_NONBLOCK;
|
||||||
|
static int *__libposix_nb_fds;
|
||||||
|
static int __libposix_nb_fds_size;
|
||||||
|
static int __libposix_nb_fds_used;
|
||||||
|
|
||||||
typedef enum SeekTypes
|
typedef enum SeekTypes
|
||||||
{
|
{
|
||||||
SeekSet = 0,
|
SeekSet = 0,
|
||||||
|
@ -117,6 +122,53 @@ __libposix_should_close_on_exec(int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__libposix_set_non_blocking(int fd, int enable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if(__libposix_nb_fds_size == __libposix_nb_fds_used){
|
||||||
|
__libposix_nb_fds_size += 8;
|
||||||
|
__libposix_nb_fds = realloc(__libposix_nb_fds, __libposix_nb_fds_size * sizeof(int));
|
||||||
|
i = __libposix_nb_fds_size;
|
||||||
|
while(i > __libposix_nb_fds_used)
|
||||||
|
__libposix_nb_fds[--i] = -1;
|
||||||
|
}
|
||||||
|
/* remove fd if already present */
|
||||||
|
i = 0;
|
||||||
|
while(i < __libposix_nb_fds_size){
|
||||||
|
if(__libposix_nb_fds[i] == fd){
|
||||||
|
__libposix_nb_fds[i] = -1;
|
||||||
|
--__libposix_nb_fds_used;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if(enable){
|
||||||
|
/* add fd to ensure it will not block */
|
||||||
|
i = 0;
|
||||||
|
while(i < __libposix_nb_fds_size){
|
||||||
|
if(__libposix_nb_fds[i] == -1){
|
||||||
|
__libposix_nb_fds[i] = fd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
++__libposix_nb_fds_used;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
__libposix_should_not_block(int fd)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while(i < __libposix_nb_fds_size){
|
||||||
|
if(__libposix_nb_fds[i] == fd)
|
||||||
|
return 1;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
libposix_translate_open(PosixOpenTranslator translation)
|
libposix_translate_open(PosixOpenTranslator translation)
|
||||||
{
|
{
|
||||||
|
@ -295,8 +347,11 @@ POSIX_open(int *errnop, const char *name, int flags, int mode)
|
||||||
} else {
|
} else {
|
||||||
f = ocreate(name, (unsigned int)omode, (unsigned int)cperm);
|
f = ocreate(name, (unsigned int)omode, (unsigned int)cperm);
|
||||||
}
|
}
|
||||||
if(f >= 0)
|
if(f >= 0){
|
||||||
|
if(flags & __libposix_O_NONBLOCK)
|
||||||
|
__libposix_set_non_blocking(f, 1);
|
||||||
return f;
|
return f;
|
||||||
|
}
|
||||||
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_open);
|
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_open);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -308,40 +363,60 @@ FailWithError:
|
||||||
long
|
long
|
||||||
POSIX_read(int *errnop, int fd, char *buf, size_t len)
|
POSIX_read(int *errnop, int fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
long r;
|
long r, wkp = 0;
|
||||||
|
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
*errnop = __libposix_get_errno(PosixEBADF);
|
*errnop = __libposix_get_errno(PosixEBADF);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
OnIgnoredSignalInterrupt:
|
OnIgnoredSignalInterrupt:
|
||||||
|
if(__libposix_should_not_block(fd))
|
||||||
|
wkp = awake(2);
|
||||||
r = sys_pread(fd, buf, len, -1);
|
r = sys_pread(fd, buf, len, -1);
|
||||||
if(r < 0){
|
if(r < 0){
|
||||||
|
if(wkp){
|
||||||
|
if(!awakened(wkp))
|
||||||
|
forgivewkp(wkp);
|
||||||
|
*errnop = __libposix_get_errno(PosixEAGAIN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(__libposix_restart_syscall())
|
if(__libposix_restart_syscall())
|
||||||
goto OnIgnoredSignalInterrupt;
|
goto OnIgnoredSignalInterrupt;
|
||||||
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_read);
|
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_read);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(wkp)
|
||||||
|
forgivewkp(wkp);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
POSIX_write(int *errnop, int fd, const void *buf, size_t len)
|
POSIX_write(int *errnop, int fd, const void *buf, size_t len)
|
||||||
{
|
{
|
||||||
long w;
|
long w, wkp = 0;
|
||||||
|
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
*errnop = __libposix_get_errno(PosixEBADF);
|
*errnop = __libposix_get_errno(PosixEBADF);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
OnIgnoredSignalInterrupt:
|
OnIgnoredSignalInterrupt:
|
||||||
|
if(__libposix_should_not_block(fd))
|
||||||
|
wkp = awake(2);
|
||||||
w = sys_pwrite(fd, buf, len, -1);
|
w = sys_pwrite(fd, buf, len, -1);
|
||||||
if(w < 0){
|
if(w < 0){
|
||||||
|
if(wkp){
|
||||||
|
if(!awakened(wkp))
|
||||||
|
forgivewkp(wkp);
|
||||||
|
*errnop = __libposix_get_errno(PosixEAGAIN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(__libposix_restart_syscall())
|
if(__libposix_restart_syscall())
|
||||||
goto OnIgnoredSignalInterrupt;
|
goto OnIgnoredSignalInterrupt;
|
||||||
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_write);
|
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_write);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(wkp)
|
||||||
|
forgivewkp(wkp);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,40 +445,60 @@ POSIX_lseek(int *errnop, int fd, off_t pos, int whence)
|
||||||
long
|
long
|
||||||
POSIX_pread(int *errnop, int fd, char *buf, size_t len, long offset)
|
POSIX_pread(int *errnop, int fd, char *buf, size_t len, long offset)
|
||||||
{
|
{
|
||||||
long r;
|
long r, wkp = 0;
|
||||||
|
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
*errnop = __libposix_get_errno(PosixEBADF);
|
*errnop = __libposix_get_errno(PosixEBADF);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
OnIgnoredSignalInterrupt:
|
OnIgnoredSignalInterrupt:
|
||||||
|
if(__libposix_should_not_block(fd))
|
||||||
|
wkp = awake(2);
|
||||||
r = sys_pread(fd, buf, len, offset);
|
r = sys_pread(fd, buf, len, offset);
|
||||||
if(r < 0){
|
if(r < 0){
|
||||||
|
if(wkp){
|
||||||
|
if(!awakened(wkp))
|
||||||
|
forgivewkp(wkp);
|
||||||
|
*errnop = __libposix_get_errno(PosixEAGAIN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(__libposix_restart_syscall())
|
if(__libposix_restart_syscall())
|
||||||
goto OnIgnoredSignalInterrupt;
|
goto OnIgnoredSignalInterrupt;
|
||||||
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_read);
|
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_read);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(wkp)
|
||||||
|
forgivewkp(wkp);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
POSIX_pwrite(int *errnop, int fd, const char *buf, size_t len, long offset)
|
POSIX_pwrite(int *errnop, int fd, const char *buf, size_t len, long offset)
|
||||||
{
|
{
|
||||||
long w;
|
long w, wkp = 0;
|
||||||
|
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
*errnop = __libposix_get_errno(PosixEBADF);
|
*errnop = __libposix_get_errno(PosixEBADF);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
OnIgnoredSignalInterrupt:
|
OnIgnoredSignalInterrupt:
|
||||||
|
if(__libposix_should_not_block(fd))
|
||||||
|
wkp = awake(2);
|
||||||
w = sys_pwrite(fd, buf, len, offset);
|
w = sys_pwrite(fd, buf, len, offset);
|
||||||
if(w < 0){
|
if(w < 0){
|
||||||
|
if(wkp){
|
||||||
|
if(!awakened(wkp))
|
||||||
|
forgivewkp(wkp);
|
||||||
|
*errnop = __libposix_get_errno(PosixEAGAIN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(__libposix_restart_syscall())
|
if(__libposix_restart_syscall())
|
||||||
goto OnIgnoredSignalInterrupt;
|
goto OnIgnoredSignalInterrupt;
|
||||||
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_write);
|
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_write);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(wkp)
|
||||||
|
forgivewkp(wkp);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,3 +976,12 @@ libposix_define_at_fdcwd(int AT_FDCWD)
|
||||||
__libposix_AT_FDCWD = AT_FDCWD;
|
__libposix_AT_FDCWD = AT_FDCWD;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
libposix_define_ononblock(int O_NONBLOCK)
|
||||||
|
{
|
||||||
|
if(__libposix_O_NONBLOCK != 0)
|
||||||
|
return -1;
|
||||||
|
__libposix_O_NONBLOCK = O_NONBLOCK;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -142,3 +142,4 @@ extern long __libposix_sighelper_set(PosixHelperCommand command, PosixSignalMask
|
||||||
extern long __libposix_sighelper_signal(PosixHelperCommand command, int target, PosixSignalInfo *siginfo);
|
extern long __libposix_sighelper_signal(PosixHelperCommand command, int target, PosixSignalInfo *siginfo);
|
||||||
extern long __libposix_sighelper_wait(PosixSignalMask set, PosixSignalInfo *siginfo);
|
extern long __libposix_sighelper_wait(PosixSignalMask set, PosixSignalInfo *siginfo);
|
||||||
extern long __libposix_sighelper_set_pgid(int target, int group_id);
|
extern long __libposix_sighelper_set_pgid(int target, int group_id);
|
||||||
|
extern void __libposix_set_non_blocking(int fd, int enable);
|
||||||
|
|
Loading…
Reference in New Issue