have you tried forking the process, then terminating the parent? All open file desciptors, including sockets, would be available to the child. The child would contain the code in try1.c.
-----Original Message----- From: Manvendra Bhangui [mailto:[EMAIL PROTECTED]] Sent: Monday, March 11, 2002 5:22 AM To: [EMAIL PROTECTED] Subject: How to pass mysql connections across exec() Hi, I have a requirement where I should be able to open connection to mysql from a server which is running continuously and pass the connection to a child of this server after it does a exec to a totally different executable. This will enable me to reuse a mysql connection initiated by one process and used by another process - which though is a child of the first process but is a totally different executable. Thus, I will be able to initiate connection pooling for a daemon like smtp without keeping on initiating mysql_real_connect() on each and every mail. I have done this by doing mysql_init() and mysql_real_connect() in the parent. In the exec'ed process, I do mysql_init() followed my vio_new() and my_net_init(). The above logic works for me, But i am not sure if I am doing the right thing. Also there is a difference in the some of the values of the mysql structure in parent and the child. Also enclosing two programs try.c and try1.c, which demonstrate the above. try does a mysql_real_connect() to open a mysql_connection with socket descriptor 3. The program try1 the uses this same descriptor to restablish the connection to the mysqld server without initiating a new socket connection. The output of the mysql structure by try is -------------------------------------------- host localhost user vpopmail pass ssh-1.5- sock /tmp/mysql.sock vers 4.0.0-alpha-log Host Info Localhost via UNIX socket info (null) db vpopmail Affected Rows 0 Insert id 0 extra_info 0 thread_id 103 packet_length 0 port 3306 client_flag 8333 server_capabilities 44 Protocol version 10 Field Count 0 Server Status 2 Server Language 8 Mysql Status 0 Free me 0 Reconnect 1 Scramble 0Q,$n~OR The output of the mysql structure by try1 is -------------------------------------------- host localhost user vpopmail pass ssh-1.5- sock /tmp/mysql.sock vers Host Info Localhost via UNIX socket info (null) db (null) Affected Rows 0 Insert id 0 extra_info 0 thread_id 0 packet_length 0 port 3306 client_flag 8333 server_capabilities 0 Protocol version 10 Field Count 0 Server Status 2 Server Language 0 Mysql Status 0 Free me 0 Reconnect 1 Scramble As you can see the following variables are not getting set in the exec'ed process. mysql.server_version mysql.thread_id mysql.server_language mysql.scramble_buff Is there anyting i am missing? (However, the program works fine and the query also works fine. The mysql show process list also shows that the connection is being reused. However I am not sure, if this method could cause any problems). The programs try.c and try1.c are below /* try.c */ #include <stdio.h> #include <fcntl.h> #include <mysql.h> main() { MYSQL mysql; mysql_init(&mysql); if (!(mysql_real_connect(&mysql, "localhost", "vpopmail", "*******", "vpopmail", 3306, 0, 0))) { fprintf(stderr, "mysql_real_connect: %s\n", mysql_error(&mysql)); return(1); } printf("host %s\n", mysql.host); printf("user %s\n", mysql.user); printf("pass %s\n", mysql.passwd); printf("sock %s\n", mysql.unix_socket); printf("vers %s\n", mysql.server_version); printf("Host Info %s\n", mysql.host_info); printf("info %s\n", mysql.info); printf("db %s\n", mysql.db); printf("Affected Rows %d\n", mysql.affected_rows); printf("Insert id %d\n", mysql.insert_id); printf("extra_info %d\n", mysql.extra_info); printf("thread_id %d\n", mysql.thread_id); printf("packet_length %d\n", mysql.packet_length); printf("port %d\n", mysql.port); printf("client_flag %d\n", mysql.client_flag); printf("server_capabilities %d\n", mysql.server_capabilities); printf("Protocol version %d\n", mysql.protocol_version); printf("Field Count %d\n", mysql.field_count); printf("Server Status %d\n", mysql.server_status); printf("Server Language %d\n", mysql.server_language); printf("Mysql Status %d\n", mysql.status); printf("Free me %d\n", mysql.free_me); printf("Reconnect %d\n", mysql.reconnect); printf("Scramble %s\n", mysql.scramble_buff); getchar(); execl("/tmp/try1", "/tmp/try1", 0); } /* try1.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pwd.h> #include <my_global.h> #include <my_sys.h> #include <mysys_err.h> #include <m_string.h> #include <m_ctype.h> #include "mysql.h" #include "mysql_version.h" #include "mysqld_error.h" #include "errmsg.h" #include <violite.h> #include <sys/stat.h> #include <signal.h> #include <time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #if defined(THREAD) && !defined(__WIN__) #include <my_pthread.h> /* because of signal() */ #endif static my_bool mysql_client_init = 0; uint mysql_port = 0; my_string mysql_unix_port = 0; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS) #include <errno.h> #define SOCKET_ERROR -1 #if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD) #define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; #define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) #define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); #else #define init_sigpipe_variables #define set_sigpipe(mysql) #define reset_sigpipe(mysql) #endif static void mysql_read_default_options(struct st_mysql_options *, const char *, const char *); static void end_server(MYSQL * mysql); static void free_old_query(MYSQL *); MYSQL *STDCALL mysqlreconnect(my_socket, MYSQL *, const char *, const char *, const char *, const char *, uint, const char *, uint); int my_net_init(NET * net, Vio * vio); main() { MYSQL mysql; MYSQL_RES *res; mysql_init(&mysql); if (!(mysqlreconnect(3, &mysql, "localhost", "vpopmail", "********", "vpopmail", 3306, 0, 0))) { fprintf(stderr, "mysql_real_connect: %s\n", mysql_error(&mysql)); return (1); } printf("host %s\n", mysql.host); printf("user %s\n", mysql.user); printf("pass %s\n", mysql.passwd); printf("sock %s\n", mysql.unix_socket); printf("vers %s\n", mysql.server_version); printf("Host Info %s\n", mysql.host_info); printf("info %s\n", mysql.info); printf("db %s\n", mysql.db); printf("Affected Rows %d\n", mysql.affected_rows); printf("Insert id %d\n", mysql.insert_id); printf("extra_info %d\n", mysql.extra_info); printf("thread_id %d\n", mysql.thread_id); printf("packet_length %d\n", mysql.packet_length); printf("port %d\n", mysql.port); printf("client_flag %d\n", mysql.client_flag); printf("server_capabilities %d\n", mysql.server_capabilities); printf("Protocol version %d\n", mysql.protocol_version); printf("Field Count %d\n", mysql.field_count); printf("Server Status %d\n", mysql.server_status); printf("Server Language %d\n", mysql.server_language); printf("Mysql Status %d\n", mysql.status); printf("Free me %d\n", mysql.free_me); printf("Reconnect %d\n", mysql.reconnect); printf("Scramble %s\n", mysql.scramble_buff); if (mysql_query(&mysql, "select * from vpopmail where pw_name='mbhangui'")) { fprintf(stderr, "mysql_query: %s\n", mysql_error(&mysql)); return (1); } res = mysql_store_result(&mysql); mysql_free_result(res); getchar(); } MYSQL *STDCALL mysqlreconnect(my_socket sock, MYSQL * mysql, const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket, uint client_flag) { char buff[NAME_LEN + USERNAME_LENGTH + 100], charset_name_buff[16]; char *end, *host_info, *charset_name; ulong pkt_length; NET *net = &mysql->net; init_sigpipe_variables DBUG_ENTER("mysql_real_connect"); DBUG_PRINT("enter", ("host: %s db: %s user: %s", host ? host : "(Null)", db ? db : "(Null)", user ? user : "(Null)")); /* * Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); net->vio = 0; /* If something goes wrong */ /* * use default options */ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) { mysql_read_default_options(&mysql->options, (mysql->options.my_cnf_file ? mysql->options.my_cnf_file : "my"), mysql->options.my_cnf_group); my_free(mysql->options.my_cnf_file, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.my_cnf_group, MYF(MY_ALLOW_ZERO_PTR)); mysql->options.my_cnf_file = mysql->options.my_cnf_group = 0; } /* * Some empty-string-tests are done because of ODBC */ if (!host || !host[0]) host = mysql->options.host; if (!user || !user[0]) user = mysql->options.user; if (!passwd) { passwd = mysql->options.password; #ifndef DONT_USE_MYSQL_PWD if (!passwd) passwd = getenv("MYSQL_PWD"); /* get it from environment (haneke) */ #endif } if (!db || !db[0]) db = mysql->options.db; if (!port) port = mysql->options.port; if (!unix_socket) unix_socket = mysql->options.unix_socket; mysql->reconnect = 1; /* Reconnect as default */ mysql->server_status = SERVER_STATUS_AUTOCOMMIT; #if defined(HAVE_SYS_UN_H) if ((!host || !strcmp(host, LOCAL_HOST)) && (unix_socket || mysql_unix_port)) { host = LOCAL_HOST; if (!unix_socket) unix_socket = mysql_unix_port; host_info = (char *) ER(CR_LOCALHOST_CONNECTION); DBUG_PRINT("info", ("Using UNIX sock '%s'", unix_socket)); net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); } else #endif { unix_socket = 0; /* This is not used */ if (!port) port = mysql_port; if (!host) host = LOCAL_HOST; sprintf(host_info = buff, ER(CR_TCP_CONNECTION), host); DBUG_PRINT("info", ("Server name: '%s'. TCP sock: %d", host, port)); net->vio = vio_new(sock, VIO_TYPE_TCPIP, FALSE); } if (!net->vio || my_net_init(net, net->vio)) { vio_delete(net->vio); net->vio = 0; net->last_errno = CR_OUT_OF_MEMORY; strmov(net->last_error, ER(net->last_errno)); goto error; } vio_keepalive(net->vio, TRUE); /* * Get version info */ mysql->protocol_version = PROTOCOL_VERSION; /* Assume this */ if (mysql->options.connect_timeout && vio_poll_read(net->vio, mysql->options.connect_timeout)) { net->last_errno = CR_SERVER_LOST; strmov(net->last_error, ER(net->last_errno)); goto error; } /* net_flush(net); if ((pkt_length = net_safe_read(mysql)) == packet_error) goto error; */ /* * Check if version of protocoll matches current one */ net->read_pos[0] = PROTOCOL_VERSION; mysql->protocol_version = net->read_pos[0]; DBUG_DUMP("packet", (char *) net->read_pos, 10); DBUG_PRINT("info", ("mysql protocol version %d, server=%d", PROTOCOL_VERSION, mysql->protocol_version)); if (mysql->protocol_version != PROTOCOL_VERSION) { net->last_errno = CR_VERSION_ERROR; sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, PROTOCOL_VERSION); goto error; } end = strend((char *) net->read_pos + 1); mysql->thread_id = uint4korr(end + 1); end += 5; strmake(mysql->scramble_buff, end, 8); end += 9; if (pkt_length >= (uint) (end + 1 - (char *) net->read_pos)) mysql->server_capabilities = uint2korr(end); if (pkt_length >= (uint) (end + 18 - (char *) net->read_pos)) { /* * New protocol with 16 bytes to describe server characteristics */ mysql->server_language = end[2]; mysql->server_status = uint2korr(end + 3); } /* * Set character set */ if ((charset_name = mysql->options.charset_name)) { const char *save = charsets_dir; if (mysql->options.charset_dir) charsets_dir = mysql->options.charset_dir; mysql->charset = get_charset_by_name(mysql->options.charset_name, MYF(MY_WME)); charsets_dir = save; } else if (mysql->server_language) { charset_name = charset_name_buff; sprintf(charset_name, "%d", mysql->server_language); /* In case of errors */ if (!(mysql->charset = get_charset((uint8) mysql->server_language, MYF(0)))) mysql->charset = default_charset_info; /* shouldn't be fatal */ } else mysql->charset = default_charset_info; if (!mysql->charset) { net->last_errno = CR_CANT_READ_CHARSET; if (mysql->options.charset_dir) sprintf(net->last_error, ER(net->last_errno), charset_name ? charset_name : "unknown", mysql->options.charset_dir); else { char cs_dir_name[FN_REFLEN]; get_charsets_dir(cs_dir_name); sprintf(net->last_error, ER(net->last_errno), charset_name ? charset_name : "unknown", cs_dir_name); } goto error; } /* * Save connection information */ if (!user) user = ""; if (!passwd) passwd = ""; if (!my_multi_malloc (MYF(0), &mysql->host_info, (uint) strlen(host_info) + 1, &mysql->host, (uint) strlen(host) + 1, &mysql->unix_socket, unix_socket ? (uint) strlen(unix_socket) + 1 : (uint) 1, &mysql->server_version, (uint) (end - (char *) net->read_pos), NullS) || !(mysql->user = my_strdup(user, MYF(0))) || !(mysql->passwd = my_strdup(passwd, MYF(0)))) { strmov(net->last_error, ER(net->last_errno = CR_OUT_OF_MEMORY)); goto error; } strmov(mysql->host_info, host_info); strmov(mysql->host, host); if (unix_socket) strmov(mysql->unix_socket, unix_socket); else mysql->unix_socket = 0; strmov(mysql->server_version, (char *) net->read_pos + 1); mysql->port = port; client_flag |= mysql->options.client_flag; /* * Send client information for access check */ client_flag |= CLIENT_CAPABILITIES; if (db) client_flag |= CLIENT_CONNECT_WITH_DB; #ifdef HAVE_COMPRESS if ((mysql->server_capabilities & CLIENT_COMPRESS) && (mysql->options.compress || (client_flag & CLIENT_COMPRESS))) client_flag |= CLIENT_COMPRESS; /*- We will use compression */ else #endif client_flag &= ~CLIENT_COMPRESS; int2store(buff, client_flag); mysql->client_flag = client_flag; DBUG_PRINT("info", ("Server version = '%s' capabilites: %ld status: %d client_flag: %d", mysql->server_version, mysql->server_capabilities, mysql->server_status, client_flag)); int3store(buff + 2, max_allowed_packet); if (user && user[0]) strmake(buff + 5, user, 32); /* Max user name */ DBUG_PRINT("info", ("user: %s", buff + 5)); end = scramble(strend(buff + 5) + 1, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { end = strmake(end + 1, db, NAME_LEN); mysql->db = my_strdup(db, MYF(MY_WME)); db = 0; } /*- if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net) || net_safe_read(mysql) == packet_error) goto error; */ if (client_flag & CLIENT_COMPRESS) /* We will use compression */ net->compress = 1; /* if (db && mysql_select_db(mysql, db)) goto error;*/ if (mysql->options.init_command) { my_bool reconnect = mysql->reconnect; mysql->reconnect = 0; if (mysql_query(mysql, mysql->options.init_command)) goto error; mysql_free_result(mysql_use_result(mysql)); mysql->reconnect = reconnect; } if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) goto error; DBUG_PRINT("exit", ("Mysql handler: %lx", mysql)); reset_sigpipe(mysql); DBUG_RETURN(mysql); error: reset_sigpipe(mysql); DBUG_PRINT("error", ("message: %u (%s)", net->last_errno, net->last_error)); { /* Free alloced memory */ my_bool free_me = mysql->free_me; end_server(mysql); mysql->free_me = 0; mysql_close(mysql); mysql->free_me = free_me; } DBUG_RETURN(0); } /*************************************************************************** * ** Get options from my.cnf **************************************************************************** / static const char *default_options[] = { "port", "socket", "compress", "password", "pipe", "timeout", "user", "init-command", "host", "database", "debug", "return-found-rows", "ssl-key", "ssl-cert", "ssl-ca", "ssl-capath", "ssl-cipher" "character-set-dir", "default-character-set", "interactive-timeout", "connect_timeout", "replication-probe", "enable-reads-from-master", "repl-parse-query", NullS }; static TYPELIB option_types = { array_elements(default_options) - 1, "options", default_options }; static void mysql_read_default_options(struct st_mysql_options *options, const char *filename, const char *group) { int argc; char *argv_buff[1], **argv; const char *groups[3]; DBUG_ENTER("mysql_read_default_options"); DBUG_PRINT("enter", ("file: %s group: %s", filename, group ? group : "NULL")); argc = 1; argv = argv_buff; argv_buff[0] = (char *) "client"; groups[0] = (char *) "client"; groups[1] = (char *) group; groups[2] = 0; load_defaults(filename, groups, &argc, &argv); if (argc != 1) /* * If some default option */ { char **option = argv; while (*++option) { /* * DBUG_PRINT("info",("option: %s",option[0])); */ if (option[0][0] == '-' && option[0][1] == '-') { char *end = strcend(*option, '='); char *opt_arg = 0; if (*end) { opt_arg = end + 1; *end = 0; /* * Remove '=' */ } switch (find_type(*option + 2, &option_types, 2)) { case 1: /* * port */ if (opt_arg) options->port = atoi(opt_arg); break; case 2: /* * socket */ if (opt_arg) { my_free(options->unix_socket, MYF(MY_ALLOW_ZERO_PTR)); options->unix_socket = my_strdup(opt_arg, MYF(MY_WME)); } break; case 3: /* * compress */ options->compress = 1; break; case 4: /* password */ if (opt_arg) { my_free(options->password, MYF(MY_ALLOW_ZERO_PTR)); options->password = my_strdup(opt_arg, MYF(MY_WME)); } break; case 5: /* pipe */ options->named_pipe = 1; /* Force named pipe */ break; case 20: /* connect_timeout */ case 6: /* timeout */ if (opt_arg) options->connect_timeout = atoi(opt_arg); break; case 7: /* * user */ if (opt_arg) { my_free(options->user, MYF(MY_ALLOW_ZERO_PTR)); options->user = my_strdup(opt_arg, MYF(MY_WME)); } break; case 8: /* * init-command */ if (opt_arg) { my_free(options->init_command, MYF(MY_ALLOW_ZERO_PTR)); options->init_command = my_strdup(opt_arg, MYF(MY_WME)); } break; case 9: /* * host */ if (opt_arg) { my_free(options->host, MYF(MY_ALLOW_ZERO_PTR)); options->host = my_strdup(opt_arg, MYF(MY_WME)); } break; case 10: /* * database */ if (opt_arg) { my_free(options->db, MYF(MY_ALLOW_ZERO_PTR)); options->db = my_strdup(opt_arg, MYF(MY_WME)); } break; case 11: /* * debug */ mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace"); break; case 12: /* * return-found-rows */ options->client_flag |= CLIENT_FOUND_ROWS; break; case 13: /* * Ignore SSL options */ case 14: case 15: case 16: break; case 17: /* * charset-lib */ my_free(options->charset_dir, MYF(MY_ALLOW_ZERO_PTR)); options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); break; case 18: my_free(options->charset_name, MYF(MY_ALLOW_ZERO_PTR)); options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); break; case 19: /* * Interactive-timeout */ options->client_flag |= CLIENT_INTERACTIVE; break; case 21: /* * replication probe */ options->rpl_probe = 1; break; case 22: /* * enable-reads-from-master */ options->rpl_parse = 1; break; case 23: /* * repl-parse-query */ options->no_master_reads = 0; break; default: DBUG_PRINT("warning", ("unknown option: %s", option[0])); } } } } free_defaults(argv); DBUG_VOID_RETURN; } /************************************************************************** ** Shut down connection **************************************************************************/ static void end_server(MYSQL * mysql) { DBUG_ENTER("end_server"); if (mysql->net.vio != 0) { init_sigpipe_variables DBUG_PRINT("info", ("Net: %s", vio_description(mysql->net.vio))); set_sigpipe(mysql); vio_delete(mysql->net.vio); reset_sigpipe(mysql); mysql->net.vio = 0; /* Marker */ } net_end(&mysql->net); free_old_query(mysql); DBUG_VOID_RETURN; } static void free_old_query(MYSQL * mysql) { DBUG_ENTER("free_old_query"); if (mysql->fields) free_root(&mysql->field_alloc, MYF(0)); init_alloc_root(&mysql->field_alloc, 8192, 0); /* Assume rowlength < 8192 */ mysql->fields = 0; mysql->field_count = 0; /* For API */ DBUG_VOID_RETURN; } /* struct charset_info_st *charset; MYSQL_FIELD *fields; MEM_ROOT field_alloc; struct st_mysql_options options; char scramble_buff[9]; Set if this is the original connection, not a master or a slave we have added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave() my_bool rpl_pivot; pointers to the master, and the next slave connections, points to itself if lone connection struct st_mysql* master, *next_slave; struct st_mysql* last_used_slave; needed for round-robin slave pick needed for send/read/store/use result to work correctly with replication struct st_mysql* last_used_con; } MYSQL; */ Regards Manny --------------------------------------------------------------------- Before posting, please check: http://www.mysql.com/manual.php (the manual) http://lists.mysql.com/ (the list archive) To request this thread, e-mail <[EMAIL PROTECTED]> To unsubscribe, e-mail <[EMAIL PROTECTED]> Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php --------------------------------------------------------------------- Before posting, please check: http://www.mysql.com/manual.php (the manual) http://lists.mysql.com/ (the list archive) To request this thread, e-mail <[EMAIL PROTECTED]> To unsubscribe, e-mail <[EMAIL PROTECTED]> Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php