2008-11-11 23:54:25 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
#include <stdio.h>
|
2008-11-11 23:54:25 -08:00
|
|
|
#include <errno.h>
|
2011-06-09 07:54:24 -07:00
|
|
|
#include <math.h>
|
|
|
|
|
2016-06-13 12:44:10 -07:00
|
|
|
#ifdef HAVE_IEEEFP_H
|
|
|
|
# include <ieeefp.h> /* for Solaris */
|
2012-12-02 23:30:33 -08:00
|
|
|
#endif
|
|
|
|
|
2011-06-09 07:54:24 -07:00
|
|
|
#ifdef HAVE_ISFINITE
|
2018-01-02 21:23:10 -08:00
|
|
|
# define ECORE_FINITE(t) isfinite(t)
|
2011-06-09 07:54:24 -07:00
|
|
|
#else
|
2018-01-02 21:23:10 -08:00
|
|
|
# define ECORE_FINITE(t) finite(t)
|
2011-06-09 07:54:24 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define FIX_HZ 1
|
|
|
|
|
|
|
|
#ifdef FIX_HZ
|
2018-01-02 21:23:10 -08:00
|
|
|
# include <sys/param.h>
|
2011-06-09 07:54:24 -07:00
|
|
|
# ifndef HZ
|
|
|
|
# define HZ 100
|
|
|
|
# endif
|
|
|
|
#endif
|
2008-11-11 23:54:25 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* On Windows, pipe() is implemented with sockets.
|
|
|
|
* Contrary to Linux, Windows uses different functions
|
|
|
|
* for sockets and fd's: write() is for fd's and send
|
|
|
|
* is for sockets. So I need to put some win32 code
|
|
|
|
* here. I can't think of a solution where the win32
|
|
|
|
* code is in Evil and not here.
|
|
|
|
*/
|
|
|
|
|
2013-03-18 15:38:01 -07:00
|
|
|
#define PIPE_FD_INVALID -1
|
|
|
|
|
2008-11-11 23:54:25 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
# include <winsock2.h>
|
2019-05-17 03:52:41 -07:00
|
|
|
# include <evil_private.h> /* pipe fcntl */
|
2008-11-11 23:54:25 -08:00
|
|
|
# define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)
|
|
|
|
# define pipe_read(fd, buffer, size) recv((fd), (char *)(buffer), size, 0)
|
2009-05-29 07:32:57 -07:00
|
|
|
# define pipe_close(fd) closesocket(fd)
|
2011-10-20 22:40:39 -07:00
|
|
|
# define PIPE_FD_ERROR SOCKET_ERROR
|
2008-11-11 23:54:25 -08:00
|
|
|
#else
|
2017-04-17 00:55:34 -07:00
|
|
|
# ifdef HAVE_SYS_EPOLL_H
|
|
|
|
# include <sys/epoll.h>
|
|
|
|
# endif /* HAVE_SYS_EPOLL_H */
|
|
|
|
# ifdef HAVE_SYS_TIMERFD_H
|
|
|
|
# include <sys/timerfd.h>
|
|
|
|
# endif
|
2008-11-11 23:54:25 -08:00
|
|
|
# include <unistd.h>
|
|
|
|
# include <fcntl.h>
|
|
|
|
# define pipe_write(fd, buffer, size) write((fd), buffer, size)
|
|
|
|
# define pipe_read(fd, buffer, size) read((fd), buffer, size)
|
2009-05-29 07:32:57 -07:00
|
|
|
# define pipe_close(fd) close(fd)
|
2011-10-20 22:40:39 -07:00
|
|
|
# define PIPE_FD_ERROR -1
|
2008-11-11 23:54:25 -08:00
|
|
|
#endif /* ! _WIN32 */
|
|
|
|
|
2012-11-18 22:26:48 -08:00
|
|
|
#include "Ecore.h"
|
2012-02-24 03:20:25 -08:00
|
|
|
#include "ecore_private.h"
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// How of then we should retry to write to the pipe
|
2012-11-18 22:26:48 -08:00
|
|
|
#define ECORE_PIPE_WRITE_RETRY 6
|
|
|
|
|
2011-12-11 00:29:35 -08:00
|
|
|
struct _Ecore_Pipe
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
ECORE_MAGIC;
|
2011-12-11 00:29:35 -08:00
|
|
|
int fd_read;
|
|
|
|
int fd_write;
|
|
|
|
Ecore_Fd_Handler *fd_handler;
|
|
|
|
const void *data;
|
|
|
|
Ecore_Pipe_Cb handler;
|
|
|
|
unsigned int len;
|
|
|
|
int handling;
|
2015-10-04 07:34:48 -07:00
|
|
|
unsigned int already_read;
|
2011-12-11 00:29:35 -08:00
|
|
|
void *passed_data;
|
|
|
|
int message;
|
2017-04-16 20:28:41 -07:00
|
|
|
#ifndef _WIN32
|
|
|
|
int pollfd;
|
|
|
|
int timerfd;
|
|
|
|
#endif
|
2011-12-11 00:29:35 -08:00
|
|
|
Eina_Bool delete_me : 1;
|
|
|
|
};
|
|
|
|
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Pipe);
|
2008-11-11 23:54:25 -08:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
static Eina_Bool _ecore_pipe_read(void *data,
|
|
|
|
Ecore_Fd_Handler *fd_handler);
|
2010-10-17 00:03:28 -07:00
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API Ecore_Pipe *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_pipe_add(Ecore_Pipe_Cb handler,
|
|
|
|
const void *data)
|
2008-11-11 23:54:25 -08:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
return _ecore_pipe_add(handler, data);
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API void *
|
2008-11-11 23:54:25 -08:00
|
|
|
ecore_pipe_del(Ecore_Pipe *p)
|
|
|
|
{
|
2012-12-24 01:35:56 -08:00
|
|
|
if (!p) return NULL;
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2016-01-14 14:52:37 -08:00
|
|
|
return _ecore_pipe_del(p);
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API void
|
2009-04-23 00:08:50 -07:00
|
|
|
ecore_pipe_read_close(Ecore_Pipe *p)
|
2009-04-22 18:38:55 -07:00
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2009-04-22 18:38:55 -07:00
|
|
|
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_close");
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2009-04-22 18:38:55 -07:00
|
|
|
}
|
2010-10-12 17:37:12 -07:00
|
|
|
if (p->fd_handler)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
_ecore_main_fd_handler_del(ML_OBJ, ML_DAT, p->fd_handler);
|
2010-10-12 17:37:12 -07:00
|
|
|
p->fd_handler = NULL;
|
|
|
|
}
|
|
|
|
if (p->fd_read != PIPE_FD_INVALID)
|
|
|
|
{
|
|
|
|
pipe_close(p->fd_read);
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
}
|
2009-04-22 18:38:55 -07:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API int
|
2013-02-24 16:32:27 -08:00
|
|
|
ecore_pipe_read_fd(Ecore_Pipe *p)
|
|
|
|
{
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(PIPE_FD_INVALID);
|
2018-02-06 00:58:44 -08:00
|
|
|
if (!p) return PIPE_FD_INVALID;
|
2013-02-24 16:32:27 -08:00
|
|
|
return p->fd_read;
|
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API void
|
2011-05-30 09:52:19 -07:00
|
|
|
ecore_pipe_freeze(Ecore_Pipe *p)
|
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2011-05-30 09:52:19 -07:00
|
|
|
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
|
|
|
|
{
|
2011-06-06 23:37:25 -07:00
|
|
|
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_freeze");
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2011-05-30 09:52:19 -07:00
|
|
|
}
|
|
|
|
if (p->fd_handler)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
_ecore_main_fd_handler_del(ML_OBJ, ML_DAT, p->fd_handler);
|
2011-05-30 09:52:19 -07:00
|
|
|
p->fd_handler = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API void
|
2011-05-31 01:05:16 -07:00
|
|
|
ecore_pipe_thaw(Ecore_Pipe *p)
|
2011-05-30 09:52:19 -07:00
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2011-05-30 09:52:19 -07:00
|
|
|
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
|
|
|
|
{
|
2011-06-06 23:37:25 -07:00
|
|
|
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read_thaw");
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2011-05-30 09:52:19 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
if ((!p->fd_handler) && (p->fd_read != PIPE_FD_INVALID))
|
|
|
|
p->fd_handler = ecore_main_fd_handler_add(p->fd_read, ECORE_FD_READ,
|
|
|
|
_ecore_pipe_read, p,
|
|
|
|
NULL, NULL);
|
2011-05-30 09:52:19 -07:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API int
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_pipe_wait(Ecore_Pipe *p,
|
|
|
|
int message_count,
|
|
|
|
double wait)
|
2011-06-09 07:54:24 -07:00
|
|
|
{
|
2016-01-14 14:52:37 -08:00
|
|
|
return _ecore_pipe_wait(p, message_count, wait);
|
2011-06-09 07:54:24 -07:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API void
|
2009-04-23 00:08:50 -07:00
|
|
|
ecore_pipe_write_close(Ecore_Pipe *p)
|
2009-04-22 18:38:55 -07:00
|
|
|
{
|
|
|
|
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write_close");
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2009-04-22 18:38:55 -07:00
|
|
|
}
|
2010-10-12 17:37:12 -07:00
|
|
|
if (p->fd_write != PIPE_FD_INVALID)
|
|
|
|
{
|
|
|
|
pipe_close(p->fd_write);
|
|
|
|
p->fd_write = PIPE_FD_INVALID;
|
|
|
|
}
|
2009-04-22 18:38:55 -07:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API int
|
2013-02-24 16:32:27 -08:00
|
|
|
ecore_pipe_write_fd(Ecore_Pipe *p)
|
|
|
|
{
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(PIPE_FD_INVALID);
|
2018-02-06 00:58:44 -08:00
|
|
|
if (!p) return PIPE_FD_INVALID;
|
2013-02-24 16:32:27 -08:00
|
|
|
return p->fd_write;
|
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API Eina_Bool
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_pipe_write(Ecore_Pipe *p,
|
|
|
|
const void *buffer,
|
|
|
|
unsigned int nbytes)
|
2008-11-11 23:54:25 -08:00
|
|
|
{
|
|
|
|
ssize_t ret;
|
2011-10-20 22:40:39 -07:00
|
|
|
size_t already_written = 0;
|
|
|
|
int retry = ECORE_PIPE_WRITE_RETRY;
|
2012-11-06 02:49:05 -08:00
|
|
|
Eina_Bool ok = EINA_FALSE;
|
2020-06-02 19:17:18 -07:00
|
|
|
unsigned int bytes = nbytes;
|
2008-11-11 23:54:25 -08:00
|
|
|
|
|
|
|
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write");
|
2012-11-06 02:49:05 -08:00
|
|
|
goto out;
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
2009-04-22 18:38:55 -07:00
|
|
|
|
2012-11-06 02:49:05 -08:00
|
|
|
if (p->delete_me) goto out;
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2012-11-06 02:49:05 -08:00
|
|
|
if (p->fd_write == PIPE_FD_INVALID) goto out;
|
2009-04-22 18:38:55 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
do // First write the len into the pipe
|
2008-11-11 23:54:25 -08:00
|
|
|
{
|
2020-06-02 19:17:18 -07:00
|
|
|
ret = pipe_write(p->fd_write, &bytes, sizeof(bytes));
|
2010-09-29 23:09:20 -07:00
|
|
|
if (ret == sizeof(nbytes))
|
|
|
|
{
|
|
|
|
retry = ECORE_PIPE_WRITE_RETRY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (ret > 0)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// XXX What should we do here?
|
|
|
|
ERR("The length of the data was not written complete"
|
|
|
|
" to the pipe");
|
|
|
|
goto out;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else if ((ret == PIPE_FD_ERROR) && (errno == EPIPE))
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
|
|
|
pipe_close(p->fd_write);
|
|
|
|
p->fd_write = PIPE_FD_INVALID;
|
2012-11-06 02:49:05 -08:00
|
|
|
goto out;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else if ((ret == PIPE_FD_ERROR) && (errno == EINTR))
|
|
|
|
// try it again
|
2010-09-29 23:09:20 -07:00
|
|
|
;
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 04:55:26 -08:00
|
|
|
ERR("An unhandled error (ret: %zd errno: %d)"
|
2010-09-29 23:09:20 -07:00
|
|
|
"occurred while writing to the pipe the length",
|
|
|
|
ret, errno);
|
|
|
|
}
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
|
|
|
while (retry--);
|
|
|
|
|
2012-11-06 02:49:05 -08:00
|
|
|
if (retry != ECORE_PIPE_WRITE_RETRY) goto out;
|
2008-11-11 23:54:25 -08:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
do // and now pass the data to the pipe
|
2008-11-11 23:54:25 -08:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ret = pipe_write(p->fd_write,
|
2009-08-12 17:27:53 -07:00
|
|
|
((unsigned char *)buffer) + already_written,
|
|
|
|
nbytes - already_written);
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2010-09-29 23:09:20 -07:00
|
|
|
if (ret == (ssize_t)(nbytes - already_written))
|
2012-11-06 02:49:05 -08:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
ok = EINA_TRUE;
|
|
|
|
goto out;
|
2012-11-06 02:49:05 -08:00
|
|
|
}
|
2010-09-29 23:09:20 -07:00
|
|
|
else if (ret >= 0)
|
|
|
|
{
|
|
|
|
already_written -= ret;
|
|
|
|
continue;
|
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else if ((ret == PIPE_FD_ERROR) && (errno == EPIPE))
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
|
|
|
pipe_close(p->fd_write);
|
|
|
|
p->fd_write = PIPE_FD_INVALID;
|
2012-11-06 02:49:05 -08:00
|
|
|
goto out;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else if ((ret == PIPE_FD_ERROR) && (errno == EINTR))
|
|
|
|
// try it again
|
2010-09-29 23:09:20 -07:00
|
|
|
;
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 04:55:26 -08:00
|
|
|
ERR("An unhandled error (ret: %zd errno: %d)"
|
2010-09-29 23:09:20 -07:00
|
|
|
"occurred while writing to the pipe the length",
|
|
|
|
ret, errno);
|
|
|
|
}
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
|
|
|
while (retry--);
|
|
|
|
|
2012-11-06 02:49:05 -08:00
|
|
|
out:
|
|
|
|
return ok;
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
|
|
|
|
ecore: Rename EAPI macro to ECORE_API in Ecore library
Summary:
= The Rationale =
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`.
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: vtorri, raster
Reviewed By: raster
Subscribers: raster, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12271
2021-05-23 12:08:05 -07:00
|
|
|
ECORE_API Ecore_Pipe *
|
2013-02-24 16:32:27 -08:00
|
|
|
ecore_pipe_full_add(Ecore_Pipe_Cb handler,
|
|
|
|
const void *data,
|
|
|
|
int fd_read,
|
|
|
|
int fd_write,
|
|
|
|
Eina_Bool read_survive_fork,
|
2014-07-25 17:19:30 -07:00
|
|
|
Eina_Bool write_survive_fork)
|
2012-11-06 02:49:05 -08:00
|
|
|
{
|
|
|
|
Ecore_Pipe *p = NULL;
|
|
|
|
int fds[2];
|
|
|
|
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
|
|
|
if (!handler) return NULL;
|
|
|
|
|
|
|
|
p = ecore_pipe_calloc(1);
|
|
|
|
if (!p) return NULL;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if ((fd_read == -1) && (fd_write == -1))
|
2012-11-06 02:49:05 -08:00
|
|
|
{
|
2013-02-24 16:32:27 -08:00
|
|
|
if (pipe(fds))
|
|
|
|
{
|
|
|
|
ecore_pipe_mp_free(p);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
fd_read = fds[0];
|
|
|
|
fd_write = fds[1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
fd_read = (fd_read == -1) ? PIPE_FD_INVALID : fd_read;
|
|
|
|
fd_write = (fd_write == -1) ? PIPE_FD_INVALID : fd_write;
|
2012-11-06 02:49:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ECORE_MAGIC_SET(p, ECORE_MAGIC_PIPE);
|
2013-02-24 16:32:27 -08:00
|
|
|
p->fd_read = fd_read;
|
|
|
|
p->fd_write = fd_write;
|
2012-11-06 02:49:05 -08:00
|
|
|
p->handler = handler;
|
|
|
|
p->data = data;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!read_survive_fork) eina_file_close_on_exec(fd_read, EINA_TRUE);
|
|
|
|
if (!write_survive_fork) eina_file_close_on_exec(fd_write, EINA_TRUE);
|
2012-12-07 03:01:41 -08:00
|
|
|
|
2017-04-17 00:55:34 -07:00
|
|
|
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_SYS_TIMERFD_H)
|
2017-04-16 20:28:41 -07:00
|
|
|
struct epoll_event pollev = { 0 };
|
|
|
|
p->pollfd = epoll_create(1);
|
|
|
|
p->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
2017-04-18 16:55:31 -07:00
|
|
|
eina_file_close_on_exec(p->pollfd, EINA_TRUE);
|
2017-04-16 20:28:41 -07:00
|
|
|
|
2017-04-18 18:29:27 -07:00
|
|
|
pollev.data.ptr = &(p->fd_read);
|
2017-04-16 20:28:41 -07:00
|
|
|
pollev.events = EPOLLIN;
|
|
|
|
epoll_ctl(p->pollfd, EPOLL_CTL_ADD, p->fd_read, &pollev);
|
|
|
|
|
2017-04-18 18:29:27 -07:00
|
|
|
pollev.data.ptr = &(p->timerfd);
|
2017-04-16 20:28:41 -07:00
|
|
|
pollev.events = EPOLLIN;
|
|
|
|
epoll_ctl(p->pollfd, EPOLL_CTL_ADD, p->timerfd, &pollev);
|
|
|
|
#endif
|
|
|
|
|
2017-04-17 17:55:50 -07:00
|
|
|
if (fcntl(p->fd_read, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2017-11-08 22:59:04 -08:00
|
|
|
p->fd_handler = ecore_main_fd_handler_add(p->fd_read, ECORE_FD_READ,
|
|
|
|
_ecore_pipe_read, p, NULL, NULL);
|
2014-07-25 17:19:30 -07:00
|
|
|
return p;
|
2013-02-24 16:32:27 -08:00
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// Private functions
|
2013-02-24 16:32:27 -08:00
|
|
|
Ecore_Pipe *
|
|
|
|
_ecore_pipe_add(Ecore_Pipe_Cb handler,
|
|
|
|
const void *data)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
return ecore_pipe_full_add(handler, data, -1, -1, EINA_FALSE, EINA_FALSE);
|
2012-11-06 02:49:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_ecore_pipe_del(Ecore_Pipe *p)
|
|
|
|
{
|
|
|
|
void *data = NULL;
|
|
|
|
|
|
|
|
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_del");
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-04-17 00:55:34 -07:00
|
|
|
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_SYS_TIMERFD_H)
|
2017-04-16 20:28:41 -07:00
|
|
|
epoll_ctl(p->pollfd, EPOLL_CTL_DEL, p->fd_read, NULL);
|
|
|
|
epoll_ctl(p->pollfd, EPOLL_CTL_DEL, p->timerfd, NULL);
|
|
|
|
if (p->timerfd >= 0) close(p->timerfd);
|
|
|
|
if (p->pollfd >= 0) close(p->pollfd);
|
2017-04-17 22:16:53 -07:00
|
|
|
p->timerfd = PIPE_FD_INVALID;
|
|
|
|
p->pollfd = PIPE_FD_INVALID;
|
2017-04-16 20:28:41 -07:00
|
|
|
#endif
|
2012-11-06 02:49:05 -08:00
|
|
|
p->delete_me = EINA_TRUE;
|
|
|
|
if (p->handling > 0) return (void *)p->data;
|
2017-11-08 22:59:04 -08:00
|
|
|
if (p->fd_handler) _ecore_main_fd_handler_del(ML_OBJ, ML_DAT,
|
|
|
|
p->fd_handler);
|
2012-11-06 02:49:05 -08:00
|
|
|
if (p->fd_read != PIPE_FD_INVALID) pipe_close(p->fd_read);
|
|
|
|
if (p->fd_write != PIPE_FD_INVALID) pipe_close(p->fd_write);
|
2016-07-11 06:02:45 -07:00
|
|
|
p->fd_handler = NULL;
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
p->fd_write = PIPE_FD_INVALID;
|
2012-11-06 02:49:05 -08:00
|
|
|
data = (void *)p->data;
|
|
|
|
ecore_pipe_mp_free(p);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2017-04-17 22:16:53 -07:00
|
|
|
static void
|
|
|
|
_ecore_pipe_unhandle(Ecore_Pipe *p)
|
|
|
|
{
|
|
|
|
p->handling--;
|
2017-11-08 22:59:04 -08:00
|
|
|
if (p->delete_me) _ecore_pipe_del(p);
|
2017-04-17 22:16:53 -07:00
|
|
|
}
|
|
|
|
|
2017-04-17 00:55:34 -07:00
|
|
|
#if ! defined(HAVE_SYS_EPOLL_H) || ! defined(HAVE_SYS_TIMERFD_H)
|
2012-11-06 02:49:05 -08:00
|
|
|
int
|
|
|
|
_ecore_pipe_wait(Ecore_Pipe *p,
|
|
|
|
int message_count,
|
|
|
|
double wait)
|
|
|
|
{
|
|
|
|
struct timeval tv, *t;
|
2015-08-27 00:58:10 -07:00
|
|
|
fd_set rset, wset, exset;
|
2012-11-06 02:49:05 -08:00
|
|
|
double end = 0.0;
|
|
|
|
double timeout;
|
|
|
|
int ret;
|
|
|
|
int total = 0;
|
|
|
|
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
|
2017-11-08 22:59:04 -08:00
|
|
|
if (p->fd_read == PIPE_FD_INVALID) return -1;
|
2012-11-06 02:49:05 -08:00
|
|
|
|
|
|
|
FD_ZERO(&rset);
|
2015-08-27 00:58:10 -07:00
|
|
|
FD_ZERO(&wset);
|
|
|
|
FD_ZERO(&exset);
|
2012-11-06 02:49:05 -08:00
|
|
|
FD_SET(p->fd_read, &rset);
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (wait >= 0.0) end = ecore_time_get() + wait;
|
2012-11-06 02:49:05 -08:00
|
|
|
timeout = wait;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
while ((message_count > 0) && ((timeout > 0.0) || (wait <= 0.0)))
|
2012-11-06 02:49:05 -08:00
|
|
|
{
|
|
|
|
if (wait >= 0.0)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// finite() tests for NaN, too big, too small, and infinity.
|
2017-03-21 11:11:19 -07:00
|
|
|
if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
|
2016-12-19 16:31:21 -08:00
|
|
|
{
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
}
|
|
|
|
else if (timeout > 0.0)
|
|
|
|
{
|
|
|
|
int sec, usec;
|
2012-11-06 02:49:05 -08:00
|
|
|
#ifdef FIX_HZ
|
2016-12-19 16:31:21 -08:00
|
|
|
timeout += (0.5 / HZ);
|
2017-04-16 20:28:41 -07:00
|
|
|
#endif
|
2016-12-19 16:31:21 -08:00
|
|
|
sec = (int)timeout;
|
|
|
|
usec = (int)((timeout - (double)sec) * 1000000);
|
|
|
|
tv.tv_sec = sec;
|
|
|
|
tv.tv_usec = usec;
|
|
|
|
}
|
|
|
|
t = &tv;
|
2012-11-06 02:49:05 -08:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else t = NULL;
|
2012-11-06 02:49:05 -08:00
|
|
|
|
2015-08-27 00:58:10 -07:00
|
|
|
ret = main_loop_select(p->fd_read + 1, &rset, &wset, &exset, t);
|
2012-11-06 02:49:05 -08:00
|
|
|
|
|
|
|
if (ret > 0)
|
|
|
|
{
|
2017-04-17 22:16:53 -07:00
|
|
|
p->handling++;
|
2012-11-06 02:49:05 -08:00
|
|
|
_ecore_pipe_read(p, NULL);
|
|
|
|
message_count -= p->message;
|
|
|
|
total += p->message;
|
|
|
|
p->message = 0;
|
2017-04-17 22:16:53 -07:00
|
|
|
_ecore_pipe_unhandle(p);
|
2012-11-06 02:49:05 -08:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else if (ret == 0) break;
|
2012-11-06 02:49:05 -08:00
|
|
|
else if (errno != EINTR)
|
|
|
|
{
|
2015-07-31 00:58:19 -07:00
|
|
|
if (p->fd_read != PIPE_FD_INVALID)
|
|
|
|
{
|
|
|
|
close(p->fd_read);
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
}
|
2012-11-06 02:49:05 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (wait >= 0.0) timeout = end - ecore_time_get();
|
2012-11-06 02:49:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
2017-04-16 20:28:41 -07:00
|
|
|
#else
|
|
|
|
int
|
|
|
|
_ecore_pipe_wait(Ecore_Pipe *p,
|
|
|
|
int message_count,
|
|
|
|
double wait)
|
|
|
|
{
|
|
|
|
int64_t timerfdbuf;
|
|
|
|
struct epoll_event pollincoming[2];
|
|
|
|
double timeout;
|
2018-03-21 18:19:24 -07:00
|
|
|
int ret = 0;
|
2017-04-16 20:28:41 -07:00
|
|
|
int total = 0;
|
2017-11-08 22:59:04 -08:00
|
|
|
int time_exit = -1;
|
2017-04-18 18:29:27 -07:00
|
|
|
Eina_Bool fd_read_found;
|
|
|
|
Eina_Bool fd_timer_found;
|
2017-04-16 20:28:41 -07:00
|
|
|
struct itimerspec tspec_new;
|
|
|
|
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
|
2017-11-08 22:59:04 -08:00
|
|
|
if (p->fd_read == PIPE_FD_INVALID) return -1;
|
2017-04-16 20:28:41 -07:00
|
|
|
|
|
|
|
timeout = wait;
|
2017-04-18 18:29:27 -07:00
|
|
|
int sec, usec;
|
2017-11-08 22:59:04 -08:00
|
|
|
if (wait >= 0.0)
|
2017-04-16 20:28:41 -07:00
|
|
|
{
|
2017-04-18 18:29:27 -07:00
|
|
|
if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
|
2017-04-16 20:28:41 -07:00
|
|
|
{
|
2017-04-18 18:29:27 -07:00
|
|
|
tspec_new.it_value.tv_sec = 0;
|
|
|
|
tspec_new.it_value.tv_nsec = 0;
|
|
|
|
tspec_new.it_interval.tv_sec = 0;
|
|
|
|
tspec_new.it_interval.tv_nsec = 0;
|
|
|
|
time_exit = 0;
|
2017-04-16 20:28:41 -07:00
|
|
|
}
|
2017-04-18 18:29:27 -07:00
|
|
|
else
|
2017-04-16 20:28:41 -07:00
|
|
|
{
|
2017-04-18 18:29:27 -07:00
|
|
|
#ifdef FIX_HZ
|
|
|
|
timeout += (0.5 / HZ);
|
|
|
|
#endif
|
|
|
|
sec = (int)timeout;
|
|
|
|
usec = (int)((timeout - (double)sec) * 1000000000);
|
|
|
|
tspec_new.it_value.tv_sec = sec;
|
|
|
|
tspec_new.it_value.tv_nsec = (int)(usec) % 1000000000;
|
|
|
|
tspec_new.it_interval.tv_sec = 0;
|
|
|
|
tspec_new.it_interval.tv_nsec = 0;
|
|
|
|
timerfd_settime(p->timerfd, 0, &tspec_new, NULL);
|
2017-11-08 22:59:04 -08:00
|
|
|
}
|
2017-04-18 18:29:27 -07:00
|
|
|
}
|
2017-04-16 20:28:41 -07:00
|
|
|
|
2018-03-21 18:19:24 -07:00
|
|
|
while ((p->pollfd != PIPE_FD_INVALID) && (ret = epoll_wait(p->pollfd, pollincoming, 2, time_exit)) > 0)
|
2017-04-18 18:29:27 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
fd_read_found = EINA_FALSE;
|
|
|
|
fd_timer_found = EINA_FALSE;
|
|
|
|
|
|
|
|
for (int i = 0; i < ret;i++)
|
|
|
|
{
|
|
|
|
if ((&p->fd_read == pollincoming[i].data.ptr))
|
|
|
|
fd_read_found = EINA_TRUE;
|
|
|
|
if ((&p->timerfd == pollincoming[i].data.ptr))
|
|
|
|
fd_timer_found = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->handling++;
|
|
|
|
if (fd_read_found)
|
|
|
|
{
|
|
|
|
_ecore_pipe_read(p, NULL);
|
|
|
|
message_count -= p->message;
|
|
|
|
total += p->message;
|
|
|
|
p->message = 0;
|
|
|
|
if (message_count <= 0)
|
|
|
|
{
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID))
|
|
|
|
{
|
|
|
|
if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf)) <
|
|
|
|
(int)sizeof(int64_t))
|
|
|
|
WRN("Could not read timerfd data");
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
_ecore_pipe_unhandle(p);
|
2017-04-18 18:29:27 -07:00
|
|
|
}
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
if (errno != EBADF)
|
|
|
|
WRN("epoll file descriptor is not a valid");
|
|
|
|
else if (errno != EINVAL)
|
|
|
|
WRN("epoll file descriptor is not an epoll file descriptor, or maxevents is less than or equal to zero.");
|
|
|
|
else if (errno != EFAULT)
|
|
|
|
WRN("The memory area pointed to by epoll_event is not accessible with write permissions.");
|
2017-04-16 20:28:41 -07:00
|
|
|
else if (errno != EINTR)
|
2017-04-18 18:29:27 -07:00
|
|
|
WRN("The call was interrupted by a signal handler before any of the requested epoll_event "
|
|
|
|
"occurred or the timeout expired; see signal(7).");
|
2017-04-16 20:28:41 -07:00
|
|
|
}
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2012-11-06 02:49:05 -08:00
|
|
|
static void
|
|
|
|
_ecore_pipe_handler_call(Ecore_Pipe *p,
|
|
|
|
unsigned char *buf,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
void *data = (void*) p->data;
|
2014-04-24 18:29:01 -07:00
|
|
|
|
|
|
|
// clear all values of pipe first.
|
|
|
|
p->passed_data = NULL;
|
|
|
|
p->already_read = 0;
|
|
|
|
p->len = 0;
|
|
|
|
p->message++;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!p->delete_me) p->handler(data, buf, len);
|
2014-04-24 18:29:01 -07:00
|
|
|
|
|
|
|
// free p->passed_data
|
|
|
|
free(buf);
|
2010-10-12 17:35:09 -07:00
|
|
|
}
|
2008-11-11 23:54:25 -08:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_pipe_read(void *data,
|
2012-11-25 01:55:32 -08:00
|
|
|
Ecore_Fd_Handler *fd_handler EINA_UNUSED)
|
2008-11-11 23:54:25 -08:00
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
Ecore_Pipe *p = (Ecore_Pipe *)data;
|
|
|
|
int i;
|
2008-11-11 23:54:25 -08:00
|
|
|
|
2010-10-12 17:35:09 -07:00
|
|
|
p->handling++;
|
|
|
|
for (i = 0; i < 16; i++)
|
2008-11-11 23:54:25 -08:00
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
ssize_t ret;
|
2010-09-29 23:09:20 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// if we already have read some data we don't need to read the len
|
|
|
|
// but to finish the already started job
|
2010-09-29 23:09:20 -07:00
|
|
|
if (p->len == 0)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// read the len of the passed data
|
|
|
|
ret = pipe_read(p->fd_read, &p->len, sizeof(p->len));
|
|
|
|
|
|
|
|
// catch the non error case first
|
|
|
|
// read amount ok - nothing more to do
|
|
|
|
if (ret == sizeof(p->len))
|
|
|
|
;
|
|
|
|
else if (ret > 0)
|
|
|
|
{
|
|
|
|
// we got more data than we asked for - definite error
|
|
|
|
ERR("Only read %i bytes from the pipe, although"
|
|
|
|
" we need to read %i bytes.",
|
|
|
|
(int)ret, (int)sizeof(p->len));
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
else if (ret == 0)
|
|
|
|
{
|
|
|
|
// we got no data
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
// no data on first try through means an error
|
|
|
|
_ecore_pipe_handler_call(p, NULL, 0);
|
|
|
|
pipe_close(p->fd_read);
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
p->fd_handler = NULL;
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// no data after first loop try is ok
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
}
|
2009-10-25 00:02:03 -07:00
|
|
|
#ifndef _WIN32
|
2017-11-08 22:59:04 -08:00
|
|
|
else if ((ret == PIPE_FD_ERROR) &&
|
|
|
|
((errno == EINTR) || (errno == EAGAIN)))
|
2011-10-20 22:40:39 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
_ecore_pipe_unhandle(p);
|
2011-10-20 22:40:39 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("An unhandled error (ret: %i errno: %i [%s])"
|
|
|
|
"occurred while reading from the pipe the length",
|
|
|
|
(int)ret, errno, strerror(errno));
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2009-10-25 00:02:03 -07:00
|
|
|
#else
|
2017-11-08 22:59:04 -08:00
|
|
|
else // ret == PIPE_FD_ERROR is the only other case on Windows
|
2011-10-20 22:40:39 -07:00
|
|
|
{
|
|
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
|
|
|
{
|
2012-11-06 02:49:05 -08:00
|
|
|
_ecore_pipe_handler_call(p, NULL, 0);
|
2011-10-20 22:40:39 -07:00
|
|
|
pipe_close(p->fd_read);
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
p->fd_handler = NULL;
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
}
|
2009-10-25 00:02:03 -07:00
|
|
|
#endif
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
// if somehow we got less than or equal to 0 we got an errnoneous
|
|
|
|
// messages so call callback with null and len we got. this case should
|
|
|
|
// never happen
|
2011-07-18 03:34:25 -07:00
|
|
|
if (p->len == 0)
|
2011-07-06 23:23:46 -07:00
|
|
|
{
|
2012-11-06 02:49:05 -08:00
|
|
|
_ecore_pipe_handler_call(p, NULL, 0);
|
2011-07-06 23:23:46 -07:00
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// we dont have a buffer to hold the data, so alloc it
|
2010-09-29 23:09:20 -07:00
|
|
|
if (!p->passed_data)
|
2011-07-06 23:23:46 -07:00
|
|
|
{
|
|
|
|
p->passed_data = malloc(p->len);
|
2017-11-08 22:59:04 -08:00
|
|
|
// alloc failed - error case
|
2011-07-06 23:23:46 -07:00
|
|
|
if (!p->passed_data)
|
|
|
|
{
|
2012-11-06 02:49:05 -08:00
|
|
|
_ecore_pipe_handler_call(p, NULL, 0);
|
2017-11-08 22:59:04 -08:00
|
|
|
// close the pipe
|
2011-07-06 23:23:46 -07:00
|
|
|
pipe_close(p->fd_read);
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
p->fd_handler = NULL;
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
}
|
2008-11-11 23:54:25 -08:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// and read the passed data
|
2010-09-29 23:09:20 -07:00
|
|
|
ret = pipe_read(p->fd_read,
|
2009-08-12 17:27:53 -07:00
|
|
|
((unsigned char *)p->passed_data) + p->already_read,
|
|
|
|
p->len - p->already_read);
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// catch the non error case first
|
|
|
|
// if we read enough data to finish the message/buffer
|
2017-02-10 20:05:44 -08:00
|
|
|
if (ret == (ssize_t)(p->len - p->already_read))
|
2014-04-24 18:29:01 -07:00
|
|
|
_ecore_pipe_handler_call(p, p->passed_data, p->len);
|
2011-07-06 23:23:46 -07:00
|
|
|
else if (ret > 0)
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// more data left to read
|
|
|
|
p->already_read += (unsigned int)ret;
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
else if (ret == 0)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// 0 bytes to read - could be more to read next select wake up
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2009-10-25 00:02:03 -07:00
|
|
|
#ifndef _WIN32
|
2011-04-20 07:15:33 -07:00
|
|
|
else if ((ret == PIPE_FD_ERROR) &&
|
2011-01-20 22:25:36 -08:00
|
|
|
((errno == EINTR) || (errno == EAGAIN)))
|
2011-07-06 23:23:46 -07:00
|
|
|
{
|
|
|
|
_ecore_pipe_unhandle(p);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2010-09-29 23:09:20 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("An unhandled error (ret: %zd errno: %d)"
|
|
|
|
"occurred while reading from the pipe the data",
|
|
|
|
ret, errno);
|
2010-10-12 17:35:09 -07:00
|
|
|
_ecore_pipe_unhandle(p);
|
2010-09-29 23:09:20 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2009-10-25 00:02:03 -07:00
|
|
|
#else
|
2017-11-08 22:59:04 -08:00
|
|
|
else // ret == PIPE_FD_ERROR is the only other case on Windows
|
2009-10-25 00:02:03 -07:00
|
|
|
{
|
|
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
|
|
|
{
|
2012-11-06 02:49:05 -08:00
|
|
|
_ecore_pipe_handler_call(p, NULL, 0);
|
2009-10-25 00:02:03 -07:00
|
|
|
pipe_close(p->fd_read);
|
|
|
|
p->fd_read = PIPE_FD_INVALID;
|
|
|
|
p->fd_handler = NULL;
|
2010-10-12 17:35:09 -07:00
|
|
|
_ecore_pipe_unhandle(p);
|
2009-10-25 00:02:03 -07:00
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
else break;
|
2009-10-25 00:02:03 -07:00
|
|
|
}
|
|
|
|
#endif
|
2008-11-11 23:54:25 -08:00
|
|
|
}
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2010-10-12 17:35:09 -07:00
|
|
|
_ecore_pipe_unhandle(p);
|
2008-11-11 23:54:25 -08:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
|