//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void zmqdrv_process_exit(ErlDrvData handle, ErlDrvMonitor* monitor) { zmq_drv_t* drv = reinterpret_cast<zmq_drv_t*>(handle); ErlDrvTermData pid = driver_get_monitored_process(drv->port, monitor); zmqdrv_fprintf("detected death of %lu process\r\n", pid); zmq_sock_info* si = drv->get_socket_info(pid); assert(NULL != si); zmqdrv_fprintf("force close %p\r\n", si->socket); driver_demonitor_process(drv->port, &si->monitor); if (si->busy) { // Remove socket from vm polling driver_select(drv->port, si->fd, ERL_DRV_READ, 0); } drv->zmq_pid_socket.erase(pid); drv->zmq_fd_socket.erase(si->fd); //zmq_close(Socket) is called in ~zmq_sock_info delete si; }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ static void wrap_zmq_close(zmq_drv_t *drv) { ErlDrvTermData caller = driver_caller(drv->port); zmq_sock_info* si = drv->get_socket_info(caller); if (!si) { reply_error(drv->port, caller, ENODEV); return; } zmqdrv_fprintf("close %p\r\n", si->socket); driver_demonitor_process(drv->port, &si->monitor); if (si->busy) { // Remove socket from vm polling driver_select(drv->port, si->fd, ERL_DRV_READ, 0); } drv->zmq_pid_socket.erase(caller); drv->zmq_fd_socket.erase(si->fd); //zmq_close(Socket) is called in ~zmq_sock_info delete si; reply_ok(drv->port, caller); }
zmq_drv_t::~zmq_drv_t() { for (zmq_pid_sockets_map_t::iterator it = zmq_pid_sockets.begin(); it != zmq_pid_sockets.end(); ++it) driver_demonitor_process(port, &it->second.monitor); for (zmq_fd_sockets_map_t::iterator it = zmq_fd_sockets.begin(); it != zmq_fd_sockets.end(); ++it) driver_select(port, (ErlDrvEvent)it->first, ERL_DRV_READ, 0); for (zmq_sock_info *it=zmq_sock_infos, *next=(it ? it->next : NULL); it; it = next) { next = it->next; delete (&*it); } zmq_sockets.clear(); zmq_idxs.clear(); zmq_pid_sockets.clear(); zmq_fd_sockets.clear(); if (zmq_context) { zmqdrv_fprintf("calling zmq_term(context) ...\r\n"); zmq_term(zmq_context); zmqdrv_fprintf("terminated zmq context\r\n"); } }
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) { WxeApp * app = (WxeApp *) wxTheApp; ErlDrvMonitor monitor; driver_monitor_process(port, process, &monitor); // Should we be able to handle commands when recursing? probably erl_drv_mutex_lock(wxe_batch_locker_m); //fprintf(stderr, "\r\nCB Start ");fflush(stderr); app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process); //fprintf(stderr, ".. done \r\n");fflush(stderr); wxe_batch_caller = 0; erl_drv_mutex_unlock(wxe_batch_locker_m); driver_demonitor_process(port, &monitor); }
int zmq_drv_t::del_socket(uint32_t idx) { zmq_sock_info* s; int ret = -1; zmq_idx_socket_map_t::iterator it = zmq_sockets.find(idx); if (it == zmq_sockets.end()) { zmqdrv_fprintf("warning: socket info not found for idx %d\r\n", idx); return ret; } s = it->second; s->unlink(); if (s == zmq_sock_infos) zmq_sock_infos = s->next; zmq_sockets.erase(idx); zmq_idxs.erase(s->socket); { // Remove the socket from a list of sockets owned by pid. // If this was the last socket, demonitor pid. zmq_pid_sockets_map_t::iterator it = zmq_pid_sockets.find(s->owner); if (it != zmq_pid_sockets.end()) { it->second.sockets.erase(s); if (it->second.sockets.empty()) { driver_demonitor_process(port, &it->second.monitor); zmq_pid_sockets.erase(it); } } } { zmq_fd_sockets_map_t::iterator it = zmq_fd_sockets.find(s->fd); if (it != zmq_fd_sockets.end()) { it->second.erase(s); if (it->second.empty()) { zmq_fd_sockets.erase(it->first); driver_select(port, (ErlDrvEvent)it->first, ERL_DRV_READ, 0); zmqdrv_fprintf("unregistered sig_fd(%d) with VM\r\n", it->first); } } } delete s; return 0; }
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) { WxeApp * app = (WxeApp *) wxTheApp; ErlDrvMonitor monitor; if(wxe_status != WXE_INITIATED) return; // Is thread safe if pdl have been incremented if(driver_monitor_process(port, process, &monitor) == 0) { // Should we be able to handle commands when recursing? probably // fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr); app->recurse_level++; app->dispatch_cb(wxe_queue, wxe_queue_cb_saved, process); app->recurse_level--; // fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr); driver_demonitor_process(port, &monitor); } }
// Called when an Erlang process owning sockets died. // Perform cleanup of orphan sockets owned by pid. static void zmqdrv_process_exit(ErlDrvData handle, ErlDrvMonitor* monitor) { zmq_drv_t* drv = (zmq_drv_t *)handle; ErlDrvTermData pid = driver_get_monitored_process(drv->port, monitor); zmqdrv_fprintf("detected death of %lu process\r\n", pid); driver_demonitor_process(drv->port, monitor); // Walk through the list of sockets and close the ones // owned by pid. zmq_pid_sockets_map_t::iterator it=drv->zmq_pid_sockets.find(pid); if (it != drv->zmq_pid_sockets.end()) { zmqdrv_fprintf("pid %lu has %lu sockets to be closed\r\n", pid, it->second.sockets.size()); for(zmq_sock_set_t::iterator sit = it->second.sockets.begin(); sit != it->second.sockets.end(); ++sit) drv->del_socket((*sit)->idx); } }
static void enm_stop(ErlDrvData drv_data) { EnmData* d = (EnmData*)drv_data; EnmRecv* rcv = d->waiting_recvs; ErlDrvTermData port = driver_mk_port(d->port); char refbuf[64]; int index; enm_write_select(d, 0); enm_read_select(d, 0); while (rcv != 0) { EnmRecv* p = rcv; if (driver_demonitor_process(d->port, &rcv->monitor) == 0) { index = 0; ei_encode_version(refbuf, &index); ei_encode_ref(refbuf, &index, &rcv->ref); { ErlDrvTermData term[] = { ERL_DRV_EXT2TERM, (ErlDrvTermData)refbuf, index+1, ERL_DRV_ATOM, driver_mk_atom("error"), ERL_DRV_ATOM, enm_errno_atom(ETERM), ERL_DRV_TUPLE, 2, ERL_DRV_TUPLE, 2, }; erl_drv_send_term(port, rcv->rcvr, term, sizeof term/sizeof *term); } } rcv = rcv->next; driver_free(p); } if (d->fd != -1) nn_close(d->fd); d->fd = d->sfd = d->rfd = -1; driver_free(d); }
static ErlDrvSSizeT monitor_drv_control(ErlDrvData drv_data, unsigned int command, char *ibuf, ErlDrvSizeT ilen, char **rbuf, ErlDrvSizeT rlen) { MyDrvData *data = (MyDrvData *) drv_data; char *answer = NULL; char buff[64]; ErlDrvSSizeT alen; switch (command) { case OP_I_AM_IPID: data->ipid = driver_caller(data->port); answer = "ok"; break; case OP_MONITOR_ME: { int res; OneMonitor *om = driver_alloc(sizeof(OneMonitor)); om->pid = driver_caller(data->port); om->later_id = 0; res = driver_monitor_process(data->port,om->pid,&(om->mon)); if (res < 0) { answer = "error"; driver_free(om); } else if (res > 0) { answer = "noproc"; driver_free(om); } else { om->next = data->first; data->first = om; answer = "ok"; } break; } case OP_DEMONITOR_ME: { int res; OneMonitor *p,*q = NULL; int found = 0; ErlDrvTermData pid = driver_caller(data->port); for (p = data->first; p != NULL; p = p->next) { if (p->pid == pid) { q = p; ++found; } } if (q == NULL) { answer = "not_monitored"; } else { if (q->later_id > 0) { if (found > 1) { answer = "delayd_but_more"; } else { answer = "delayed"; } } else { res = driver_demonitor_process(data->port, &(q->mon)); if (res < 0) { answer = "error"; } else if (res > 0) { if (found > 1) { answer = "gone_but_more"; } else { answer = "gone"; } } else { if (found > 1) { answer = "ok_but_more"; } else { answer = "ok"; } } } if (data->first == q) { data->first = q->next; } else { for (p = data->first; p != NULL; p = p->next) { if (p->next == q) { p->next = q->next; break; } } } driver_free(q); } break; } case OP_MONITOR_ME_LATER: { int res; OneMonitor *om = driver_alloc(sizeof(OneMonitor)); om->pid = driver_caller(data->port); om->later_id = (++(data->later_counter)); om->next = data->first; data->first = om; sprintf(buff,"ok:%d",om->later_id); answer = buff; break; } case OP_DO_DELAYED_MONITOR: { int id = 0, sign = 1, in_number = 0; OneMonitor *p, *q; char *bp; for (bp = ibuf; bp < (ibuf + ilen); ++bp) { if (*bp <= '9' && *bp >= '0') { int x = *bp - '0'; in_number++; id *= 10; id += x; } else if (*bp == '-') { if (in_number) { break; } sign = -1; ++in_number; } else { if (in_number) { break; } } } id *= sign; q = NULL; for (p = data->first; p != NULL; q = p, p = p->next) { if (p->later_id != 0 && p->later_id == id) { break; } } if (p == NULL) { answer = "not_found"; } else { int res = driver_monitor_process(data->port,p->pid,&(p->mon)); if (res != 0) { if (res < 0) { answer = "error"; } else { answer = "noproc"; } if (q == NULL) { data->first = p->next; } else { q->next = p->next; } driver_free(p); } else { p->later_id = 0; answer = "ok"; } } break; } default: answer = "unknown_op"; } if (answer == NULL) { answer = "internal_error"; } alen = strlen(answer); if (alen >= rlen) { *rbuf = driver_alloc(alen+1); } strcpy(*rbuf,answer); return alen; }