void Curl_ssl_close_all(struct SessionHandle *data) { #ifdef USE_SSL int i; /* kill the session ID cache */ if(data->state.session) { for(i=0; i< data->set.ssl.numsessions; i++) /* the single-killer function handles empty table slots */ kill_session(&data->state.session[i]); /* free the cache data */ free(data->state.session); data->state.session = NULL; } #ifdef USE_SSLEAY Curl_ossl_close_all(data); #else #ifdef USE_GNUTLS Curl_gtls_close_all(data); #endif /* USE_GNUTLS */ #endif /* USE_SSLEAY */ #else /* USE_SSL */ (void)data; #endif /* USE_SSL */ }
int do_exit(long code) { int i; free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); for (i=0 ; i<NR_TASKS ; i++) if (task[i] && task[i]->father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ (void) send_sig(SIGCHLD, task[1], 1); } for (i=0 ; i<NR_OPEN ; i++) if (current->filp[i]) sys_close(i); iput(current->pwd); current->pwd=NULL; iput(current->root); current->root=NULL; iput(current->executable); current->executable=NULL; if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; if (last_task_used_math == current) last_task_used_math = NULL; if (current->leader) kill_session(); current->state = TASK_ZOMBIE; current->exit_code = code; tell_father(current->father); schedule(); return (-1); /* just to suppress warnings */ }
int do_exit(long code) { int i; // TODO 待看页表 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); /* * 找出所有子进程,将它们的父亲设为 init 进程,将状态标记为僵尸 * 然后给 init 进程发送一个 SIGCHLD 信号,提醒 init 进程回收子进程 */ for (i=0 ; i<NR_TASKS ; i++) if (task[i] && task[i]->father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ // 最后一个参数 1 代表 privilege,此处为强制发送 (void) send_sig(SIGCHLD, task[1], 1); } // TODO 关闭文件? /* * NR_OPEN 是一个进程可以打开的最大文件数 * 而 NR_FILE 是系统在某时刻的限制文件总数 */ for (i=0 ; i<NR_OPEN ; i++) if (current->filp[i]) sys_close(i); // 进程的当前工作目录 inode iput(current->pwd); current->pwd=NULL; // 进程的根目录 inode iput(current->root); current->root=NULL; // 进程本身可执行文件的 inode iput(current->executable); current->executable=NULL; if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; if (last_task_used_math == current) last_task_used_math = NULL; /* * 如果是 session leader 会话领头进程,则向该会话所有进程发送 SIGHUP 信号 * PID, PPID, PGID, SID * http://unix.stackexchange.com/questions/18166/what-are-session-leaders-in-ps * 在同一次 ssh 会话中,用户对应的 shell 最先被启动,成为 session leader, * 所有在同一次会话中产生的进程 session id 都等于这个 session leader 的 pid * 当 session leader 退出时,它会向所有同一 session 中的进程发送 SIGHUP, * 这个信号是可以被捕获的,如果进程忽略这个 SIGHUP,它则可以以一个孤儿进程继续执行 * http://www.firefoxbug.com/index.php/archives/2782/ */ if (current->leader) kill_session(); // 将自己设为僵尸,设置退出状态码,同时告诉父进程回收子进程 current->state = TASK_ZOMBIE; current->exit_code = code; tell_father(current->father); // 如果 tell_father 中找不到父进程,自己把自己释放掉了,那也不会有机会继续执行下面代码了 schedule(); return (-1); /* just to suppress warnings */ }
static int irc_on_delete(event_owner_t *owner, void *client_data) { irc_session_t *session = client_data; if (session->party) { partymember_delete(session->party, NULL, "Deleted!"); session->party = NULL; } kill_session(session); return(0); }
/* * Delete the given session ID from the cache. */ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) { int i; for(i=0; i< conn->data->set.ssl.numsessions; i++) { struct curl_ssl_session *check = &conn->data->state.session[i]; if (check->sessionid == ssl_sessionid) { kill_session(check); break; } } }
/* * Store session id in the session cache. The ID passed on to this function * must already have been extracted and allocated the proper way for the SSL * layer. Curl_XXXX_session_free() will be called to free/kill the session ID * later on. */ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void *ssl_sessionid, size_t idsize) { long i; struct SessionHandle *data=conn->data; /* the mother of all structs */ struct curl_ssl_session *store = &data->state.session[0]; long oldest_age=data->state.session[0].age; /* zero if unused */ char *clone_host; /* Even though session ID re-use might be disabled, that only disables USING IT. We still store it here in case the re-using is again enabled for an upcoming transfer */ clone_host = strdup(conn->host.name); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ /* Now we should add the session ID and the host name to the cache, (remove the oldest if necessary) */ /* find an empty slot for us, or find the oldest */ for(i=1; (i<data->set.ssl.numsessions) && data->state.session[i].sessionid; i++) { if(data->state.session[i].age < oldest_age) { oldest_age = data->state.session[i].age; store = &data->state.session[i]; } } if(i == data->set.ssl.numsessions) /* cache is full, we must "kill" the oldest entry! */ kill_session(store); else store = &data->state.session[i]; /* use this slot */ /* now init the session struct wisely */ store->sessionid = ssl_sessionid; store->idsize = idsize; store->age = data->state.sessionage; /* set current age */ if (store->name) /* free it if there's one already present */ free(store->name); store->name = clone_host; /* clone host name */ store->remote_port = conn->remote_port; /* port number */ if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { store->sessionid = NULL; /* let caller free sessionid */ free(clone_host); return CURLE_OUT_OF_MEMORY; } return CURLE_OK; }
/** * Black list check result for try_connect call * If connection to the peer is allowed request adddress and ??? * * @param cls the message * @param peer the peer * @param address the address * @param session the session * @param result the result */ static void connect_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, int result) { struct GNUNET_MessageHeader *msg = cls; if (GNUNET_OK == result) { /* Blacklist allows to speak to this peer, forward SYN to neighbours */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received SYN message from peer `%s' at `%s'\n", GNUNET_i2s (peer), GST_plugins_a2s (address)); if (GNUNET_OK != GST_neighbours_handle_session_syn (msg, peer)) { GST_blacklist_abort_matching (address, session); kill_session (address->transport_name, session); } GNUNET_free (msg); return; } GNUNET_free (msg); if (GNUNET_SYSERR == result) return; /* check was aborted, session destroyed */ /* Blacklist denies to speak to this peer */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Discarding SYN message from `%s' due to denied blacklist check\n", GNUNET_i2s (peer)); kill_session (address->transport_name, session); }
void Curl_ssl_close_all(struct SessionHandle *data) { long i; /* kill the session ID cache */ if(data->state.session) { for(i=0; i< data->set.ssl.numsessions; i++) /* the single-killer function handles empty table slots */ kill_session(&data->state.session[i]); /* free the cache data */ free(data->state.session); data->state.session = NULL; } curlssl_close_all(data); }
//// 程序退出处理程序。在系统调用的中断处理程序中被调用。 int do_exit (long code) // code 是错误码。 { int i; // 释放当前进程代码段和数据段所占的内存页(free_page_tables()在mm/memory.c,105 行)。 free_page_tables (get_base (current->ldt[1]), get_limit (0x0f)); free_page_tables (get_base (current->ldt[2]), get_limit (0x17)); // 如果当前进程有子进程,就将子进程的father 置为1(其父进程改为进程1)。如果该子进程已经 // 处于僵死(ZOMBIE)状态,则向进程1 发送子进程终止信号SIGCHLD。 for (i = 0; i < NR_TASKS; i++) if (task[i] && task[i]->father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ (void) send_sig (SIGCHLD, task[1], 1); } // 关闭当前进程打开着的所有文件。 for (i = 0; i < NR_OPEN; i++) if (current->filp[i]) sys_close (i); // 对当前进程工作目录pwd、根目录root 以及运行程序的i 节点进行同步操作,并分别置空。 iput (current->pwd); current->pwd = NULL; iput (current->root); current->root = NULL; iput (current->executable); current->executable = NULL; // 如果当前进程是领头(leader)进程并且其有控制的终端,则释放该终端。 if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; // 如果当前进程上次使用过协处理器,则将last_task_used_math 置空。 if (last_task_used_math == current) last_task_used_math = NULL; // 如果当前进程是leader 进程,则终止所有相关进程。 if (current->leader) kill_session (); // 把当前进程置为僵死状态,并设置退出码。 current->state = TASK_ZOMBIE; current->exit_code = code; // 通知父进程,也即向父进程发送信号SIGCHLD -- 子进程将停止或终止。 tell_father (current->father); schedule (); // 重新调度进程的运行。 return (-1); /* just to suppress warnings */ }
/* * Store session id in the session cache. The ID passed on to this function * must already have been extracted and allocated the proper way for the SSL * layer. Curl_XXXX_session_free() will be called to free/kill the session ID * later on. */ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void *ssl_sessionid, size_t idsize) { int i; struct SessionHandle *data=conn->data; /* the mother of all structs */ struct curl_ssl_session *store = &data->state.session[0]; long oldest_age=data->state.session[0].age; /* zero if unused */ char *clone_host; clone_host = strdup(conn->host.name); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ /* Now we should add the session ID and the host name to the cache, (remove the oldest if necessary) */ /* find an empty slot for us, or find the oldest */ for(i=1; (i<data->set.ssl.numsessions) && data->state.session[i].sessionid; i++) { if(data->state.session[i].age < oldest_age) { oldest_age = data->state.session[i].age; store = &data->state.session[i]; } } if(i == data->set.ssl.numsessions) /* cache is full, we must "kill" the oldest entry! */ kill_session(store); else store = &data->state.session[i]; /* use this slot */ /* now init the session struct wisely */ store->sessionid = ssl_sessionid; store->idsize = idsize; store->age = data->state.sessionage; /* set current age */ store->name = clone_host; /* clone host name */ store->remote_port = conn->remote_port; /* port number */ if (!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) return CURLE_OUT_OF_MEMORY; return CURLE_OK; }
/** * Black list check result from blacklist check triggered when a * plugin gave us a new session in #plugin_env_session_start(). If * connection to the peer is disallowed, kill the session. * * @param cls NULL * @param peer the peer * @param address address associated with the request * @param session session associated with the request * @param result the result */ static void plugin_env_session_start_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, int result) { if (GNUNET_OK != result) { kill_session (address->transport_name, session); return; } if (GNUNET_YES != GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Informing verifier about inbound session's address `%s'\n", GST_plugins_a2s (address)); GST_validation_handle_address (address); } }
/** * Function called by the transport for each received message. * * @param cls closure, const char* with the name of the plugin we received the message from * @param address address and (claimed) identity of the other peer * @param message the message, NULL if we only care about * learning about the delay until we should receive again * @param session identifier used for this session (NULL for plugins * that do not offer bi-directional communication to the sender * using the same "connection") * @return how long the plugin should wait until receiving more data * (plugins that do not support this, can ignore the return value) */ struct GNUNET_TIME_Relative GST_receive_callback (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, const struct GNUNET_MessageHeader *message) { const char *plugin_name = cls; struct GNUNET_TIME_Relative ret; uint16_t type; ret = GNUNET_TIME_UNIT_ZERO; if (NULL == message) goto end; type = ntohs (message->type); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message with type %u from peer `%s'\n", type, GNUNET_i2s (&address->peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes total received"), ntohs (message->size), GNUNET_NO); GST_neighbours_notify_data_recv (address, message); switch (type) { case GNUNET_MESSAGE_TYPE_HELLO_LEGACY: /* Legacy HELLO message, discard */ return ret; case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GST_validation_handle_hello (message)) { GNUNET_break_op (0); GST_blacklist_abort_matching (address, session); } return ret; case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing PING from `%s'\n", GST_plugins_a2s (address)); if (GNUNET_OK != GST_validation_handle_ping (&address->peer, message, address, session)) { GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Processing PONG from `%s'\n", GST_plugins_a2s (address)); if (GNUNET_OK != GST_validation_handle_pong (&address->peer, message)) { GNUNET_break_op (0); GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN: /* Do blacklist check if communication with this peer is allowed */ (void) GST_blacklist_test_allowed (&address->peer, NULL, &connect_bl_check_cont, GNUNET_copy_message (message), address, session); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK: if (GNUNET_OK != GST_neighbours_handle_session_syn_ack (message, address, session)) { GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: if (GNUNET_OK != GST_neighbours_handle_session_ack (message, address, session)) { GNUNET_break_op(0); GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT: GST_neighbours_handle_disconnect_message (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA: GST_neighbours_handle_quota_message (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE: GST_neighbours_keepalive (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE: GST_neighbours_keepalive_response (&address->peer, message); break; default: /* should be payload */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload received"), ntohs (message->size), GNUNET_NO); ret = process_payload (address, session, message); break; } end: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allowing receive from peer %s to continue in %s\n", GNUNET_i2s (&address->peer), GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); return ret; }