aboutsummaryrefslogtreecommitdiffstats
path: root/lib/runtime_tools/c_src/trace_file_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/runtime_tools/c_src/trace_file_drv.c')
-rw-r--r--lib/runtime_tools/c_src/trace_file_drv.c152
1 files changed, 114 insertions, 38 deletions
diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c
index 668f6f4af3..e7fd5968c1 100644
--- a/lib/runtime_tools/c_src/trace_file_drv.c
+++ b/lib/runtime_tools/c_src/trace_file_drv.c
@@ -1,18 +1,19 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2011. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2016. All Rights Reserved.
*
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*
* %CopyrightEnd%
*/
@@ -21,6 +22,9 @@
* Purpose: Send trace messages to a file.
*/
+#ifdef __WIN32__
+#include <windows.h>
+#endif
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -31,7 +35,6 @@
#ifdef __WIN32__
# include <io.h>
# define write _write
-# define open _open
# define close _close
# define unlink _unlink
#else
@@ -40,11 +43,6 @@
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
-#ifdef VXWORKS
-# include "reclaim.h"
-#endif
-
-
/*
* Deduce MAXPATHLEN, which is the one to use in this file,
@@ -77,12 +75,8 @@
#ifdef DEBUG
-#ifndef __WIN32__
-#define ASSERT(X) do {if (!(X)) {erl_exit(1,"%s",#X);} } while(0)
-#else
#include <assert.h>
#define ASSERT(X) assert(X)
-#endif
#else
#define ASSERT(X)
#endif
@@ -176,11 +170,14 @@ static TraceFileData *first_data;
*/
static ErlDrvData trace_file_start(ErlDrvPort port, char *buff);
static void trace_file_stop(ErlDrvData handle);
-static void trace_file_output(ErlDrvData handle, char *buff, int bufflen);
+static void trace_file_output(ErlDrvData handle, char *buff,
+ ErlDrvSizeT bufflen);
+static void trace_file_outputv(ErlDrvData handle, ErlIOVec *ev);
static void trace_file_finish(void);
-static int trace_file_control(ErlDrvData handle, unsigned int command,
- char* buff, int count,
- char** res, int res_size);
+static ErlDrvSSizeT trace_file_control(ErlDrvData handle,
+ unsigned int command,
+ char* buff, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size);
static void trace_file_timeout(ErlDrvData handle);
/*
@@ -194,6 +191,12 @@ static int my_flush(TraceFileData *data);
static void put_be(unsigned n, unsigned char *s);
static void close_unlink_port(TraceFileData *data);
static int wrap_file(TraceFileData *data);
+#ifdef __WIN32__
+static int win_open(char *path, int flags, int mask);
+#define open win_open
+#else
+ErlDrvEntry *driver_init(void);
+#endif
/*
** The driver struct
@@ -212,7 +215,18 @@ ErlDrvEntry trace_file_driver_entry = {
NULL, /* void * that is not used (BC) */
trace_file_control, /* F_PTR control, port_control callback */
trace_file_timeout, /* F_PTR timeout, driver_set_timer callback */
- NULL /* F_PTR outputv, reserved */
+ trace_file_outputv, /* F_PTR outputv, reserved */
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ NULL,
};
/*
@@ -241,6 +255,7 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff)
int n, w;
static const char name[] = "trace_file_drv";
+
#ifdef HARDDEBUG
fprintf(stderr,"hello (%s)\r\n", buff);
#endif
@@ -309,9 +324,11 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff)
| O_BINARY
#endif
, 0777)) < 0) {
+ int saved_errno = errno;
if (wrap)
driver_free(wrap);
driver_free(data);
+ errno = saved_errno;
return ERL_DRV_ERROR_ERRNO;
}
@@ -347,17 +364,28 @@ static void trace_file_stop(ErlDrvData handle)
/*
** Data sent from erlang to port.
*/
-static void trace_file_output(ErlDrvData handle, char *buff, int bufflen)
+static void trace_file_outputv(ErlDrvData handle, ErlIOVec *ev)
+{
+ int i;
+ for (i = 0; i < ev->vsize; i++) {
+ if (ev->iov[i].iov_len)
+ trace_file_output(handle, ev->iov[i].iov_base,
+ ev->iov[i].iov_len);
+ }
+}
+
+static void trace_file_output(ErlDrvData handle, char *buff,
+ ErlDrvSizeT bufflen)
{
int heavy = 0;
TraceFileData *data = (TraceFileData *) handle;
unsigned char b[5] = "";
put_be((unsigned) bufflen, b + 1);
- switch (my_write(data, b, sizeof(b))) {
+ switch (my_write(data, (unsigned char *) b, sizeof(b))) {
case 1:
heavy = !0;
case 0:
- switch (my_write(data, buff, bufflen)) {
+ switch (my_write(data, (unsigned char *) buff, bufflen)) {
case 1:
heavy = !0;
case 0:
@@ -391,9 +419,10 @@ static void trace_file_output(ErlDrvData handle, char *buff, int bufflen)
/*
** Control message from erlang, we handle $f, which is flush.
*/
-static int trace_file_control(ErlDrvData handle, unsigned int command,
- char* buff, int count,
- char** res, int res_size)
+static ErlDrvSSizeT trace_file_control(ErlDrvData handle,
+ unsigned int command,
+ char* buff, ErlDrvSizeT count,
+ char** res, ErlDrvSizeT res_size)
{
if (command == 'f') {
TraceFileData *data = (TraceFileData *) handle;
@@ -505,14 +534,19 @@ static void *my_alloc(size_t size)
** A write wrapper that regards it as an error if not all data was written.
*/
static int do_write(FILETYPE fd, unsigned char *buff, int siz) {
- int w = write(fd, buff, siz);
- if (w != siz) {
- if (w >= 0) {
- errno = ENOSPC;
+ int w;
+ while (1) {
+ w = write(fd, buff, siz);
+ if (w < 0 && errno == EINTR)
+ continue;
+ else if (w != siz) {
+ if (w >= 0) {
+ errno = ENOSPC;
+ }
+ return -1;
}
- return -1;
+ return siz;
}
- return siz;
}
/*
@@ -607,8 +641,10 @@ static void close_unlink_port(TraceFileData *data)
*/
static int wrap_file(TraceFileData *data) {
if (my_flush(data) < 0) {
+ int saved_errno = errno;
close(data->fd);
data->fd = -1;
+ errno = saved_errno;
return -1;
}
close(data->fd);
@@ -624,15 +660,55 @@ static int wrap_file(TraceFileData *data) {
next_name(&data->wrap->del);
}
next_name(&data->wrap->cur);
+try_open:
data->fd = open(data->wrap->cur.name, O_WRONLY | O_TRUNC | O_CREAT
#ifdef O_BINARY
| O_BINARY
#endif
, 0777);
if (data->fd < 0) {
+ if (errno == EINTR)
+ goto try_open;
data->fd = -1;
return -1;
}
return 0;
}
+#ifdef __WIN32__
+static int win_open(char *path, int flags, int mask)
+{
+ DWORD access = 0;
+ DWORD creation = 0;
+ HANDLE fd;
+ int ret;
+ if (flags & O_WRONLY) {
+ access = GENERIC_WRITE;
+ } else if (flags & O_RDONLY) {
+ access = GENERIC_READ;
+ } else {
+ access = (GENERIC_READ | GENERIC_WRITE);
+ }
+
+ if (flags & O_CREAT) {
+ creation |= CREATE_ALWAYS;
+ } else {
+ creation |= OPEN_ALWAYS;
+ }
+
+ fd = CreateFileA(path, access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fd == INVALID_HANDLE_VALUE) {
+
+ return -1;
+ }
+
+ if ((ret = _open_osfhandle((intptr_t)fd, (flags & O_RDONLY) ? O_RDONLY : 0))
+ < 0) {
+ CloseHandle(fd);
+ }
+
+ return ret;
+}
+#endif