From d373dc49ae4c8a2d27dde23564bcaf2642cc46e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 12 Jan 2015 17:30:45 +0100 Subject: erts: Extend driver interface with emergency_close The intention of this callback is to close all sockets associated to a port. It is closed only on crashdumps. This will currently only be used for the epmd port. --- erts/emulator/beam/erl_driver.h | 5 ++++- erts/emulator/beam/global.h | 1 + erts/emulator/beam/io.c | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h index f9938fc66c..e498ac70ec 100644 --- a/erts/emulator/beam/erl_driver.h +++ b/erts/emulator/beam/erl_driver.h @@ -133,7 +133,7 @@ typedef struct { #define ERL_DRV_EXTENDED_MARKER (0xfeeeeeed) #define ERL_DRV_EXTENDED_MAJOR_VERSION 3 -#define ERL_DRV_EXTENDED_MINOR_VERSION 1 +#define ERL_DRV_EXTENDED_MINOR_VERSION 2 /* * The emulator will refuse to load a driver with a major version @@ -361,6 +361,9 @@ typedef struct erl_drv_entry { /* Called on behalf of driver_select when it is safe to release 'event'. A typical unix driver would call close(event) */ + void (*emergency_close)(ErlDrvData drv_data); + /* called when the port is closed abruptly. + specifically when erl_crash_dump is called. */ /* When adding entries here, dont forget to pad in obsolete/driver.h */ } ErlDrvEntry; diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 891046a8b5..d25daaf7b8 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -160,6 +160,7 @@ struct erts_driver_t_ { void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data); /* Might be NULL */ void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor); void (*stop_select)(ErlDrvEvent event, void*); /* Might be NULL */ + void (*emergency_close)(ErlDrvData drv_data); /* Might be NULL */ }; extern erts_driver_t *driver_list; diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 9ae973e108..4ae8fafb2c 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -7396,6 +7396,7 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) drv->timeout = de->timeout ? de->timeout : no_timeout_callback; drv->ready_async = de->ready_async; drv->process_exit = de->process_exit; + drv->emergency_close = de->emergency_close; if (de->stop_select) drv->stop_select = de->stop_select; else -- cgit v1.2.3 From 86d605807356f79f3484c36cba632ff88d4e2417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 13 Jan 2015 12:13:43 +0100 Subject: erts: Use emergency close to close epmd Closes all open socket before writing crashdump to file. --- erts/emulator/beam/global.h | 1 + erts/emulator/beam/io.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index d25daaf7b8..32a2dc43e8 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -853,6 +853,7 @@ Uint erts_port_ioq_size(Port *pp); void erts_stale_drv_select(Eterm, ErlDrvPort, ErlDrvEvent, int, int); Port *erts_get_heart_port(void); +void erts_emergency_close_ports(void); #if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_COUNT) void erts_lcnt_enable_io_lock_count(int enable); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 4ae8fafb2c..3316654790 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -7569,3 +7569,23 @@ Port *erts_get_heart_port(void) return NULL; } + +void erts_emergency_close_ports(void) +{ + int ix, max = erts_ptab_max(&erts_port); + + for (ix = 0; ix < max; ix++) { + Port *port = erts_pix2port(ix); + + if (!port) + continue; + /* only examine undead or alive ports */ + if (erts_atomic32_read_nob(&port->state) & ERTS_PORT_SFLGS_DEAD) + continue; + + /* emergency close socket */ + if (port->drv_ptr->emergency_close) { + port->drv_ptr->emergency_close((ErlDrvData) port->drv_data); + } + } +} -- cgit v1.2.3 From 1520bca342e8433089841d2c79d3d862d06479e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 13 Jan 2015 17:04:00 +0100 Subject: erts: Don't lookup invalid port for crashdump handling --- erts/emulator/beam/io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 3316654790..2ac27f024e 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -7558,7 +7558,7 @@ Port *erts_get_heart_port(void) if (!port) continue; /* only examine undead or alive ports */ - if (erts_atomic32_read_nob(&port->state) & ERTS_PORT_SFLGS_DEAD) + if (erts_atomic32_read_nob(&port->state) & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) continue; /* immediate atom compare */ reg = port->common.u.alive.reg; @@ -7580,7 +7580,7 @@ void erts_emergency_close_ports(void) if (!port) continue; /* only examine undead or alive ports */ - if (erts_atomic32_read_nob(&port->state) & ERTS_PORT_SFLGS_DEAD) + if (erts_atomic32_read_nob(&port->state) & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) continue; /* emergency close socket */ -- cgit v1.2.3 From 86e4d8ead48501f00466d685c157eaa0921d96a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 15 Jan 2015 14:40:50 +0100 Subject: erts: Check driver version before assigning callback --- erts/emulator/beam/io.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 2ac27f024e..012a7d1a4b 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -7349,6 +7349,8 @@ no_stop_select_callback(ErlDrvEvent event, void* private) erts_send_error_to_logger_nogl(dsbufp); } +#define IS_DRIVER_VERSION_GE(DE,MAJOR,MINOR) \ + ((DE)->major_version >= (MAJOR) && (DE)->minor_version >= (MINOR)) static int init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) @@ -7396,7 +7398,7 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) drv->timeout = de->timeout ? de->timeout : no_timeout_callback; drv->ready_async = de->ready_async; drv->process_exit = de->process_exit; - drv->emergency_close = de->emergency_close; + drv->emergency_close = IS_DRIVER_VERSION_GE(de,3,2) ? de->emergency_close : NULL; if (de->stop_select) drv->stop_select = de->stop_select; else @@ -7415,6 +7417,8 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) } } +#undef IS_DRIVER_VERSION_GE + void erts_destroy_driver(erts_driver_t *drv) { -- cgit v1.2.3