| 717 | | while ((i = getopt (argc, argv, "p:t:mTPiv:b:rMR:Sz:w:C:j:H:A:EQ:L")) != -1) { |
| 718 | | #endif |
| | 811 | Py_SetPythonHome (uwsgi.pyhome); |
| | 812 | #endif |
| | 813 | } |
| | 814 | |
| | 815 | |
| | 816 | |
| | 817 | |
| | 818 | #ifdef PYTHREE |
| | 819 | wchar_t pname[6]; |
| | 820 | mbstowcs (pname, "uWSGI", 6); |
| | 821 | Py_SetProgramName (pname); |
| | 822 | #else |
| | 823 | Py_SetProgramName ("uWSGI"); |
| | 824 | #endif |
| | 825 | |
| | 826 | |
| | 827 | Py_Initialize (); |
| | 828 | |
| | 829 | pyargv[0] = "uwsgi"; |
| | 830 | |
| | 831 | if (uwsgi.pyargv != NULL) { |
| | 832 | char *ap; |
| | 833 | while ((ap = strsep (&uwsgi.pyargv, " \t")) != NULL) { |
| | 834 | if (*ap != '\0') { |
| | 835 | pyargv[pyargc] = ap; |
| | 836 | pyargc++; |
| | 837 | } |
| | 838 | if (pyargc + 1 > MAX_PYARGV) |
| | 839 | break; |
| | 840 | } |
| | 841 | } |
| | 842 | |
| | 843 | PySys_SetArgv (pyargc, pyargv); |
| | 844 | |
| | 845 | |
| | 846 | uwsgi.py_apps = PyDict_New (); |
| | 847 | if (!uwsgi.py_apps) { |
| | 848 | PyErr_Print (); |
| | 849 | exit (1); |
| | 850 | } |
| | 851 | |
| | 852 | |
| | 853 | wsgi_spitout = PyCFunction_New (uwsgi_spit_method, NULL); |
| | 854 | wsgi_writeout = PyCFunction_New (uwsgi_write_method, NULL); |
| | 855 | |
| | 856 | #ifndef PYTHREE |
| | 857 | #ifndef ROCK_SOLID |
| | 858 | uwsgi_module = Py_InitModule ("uwsgi", null_methods); |
| | 859 | if (uwsgi_module == NULL) { |
| | 860 | fprintf (stderr, "could not initialize the uwsgi python module\n"); |
| | 861 | exit (1); |
| | 862 | } |
| | 863 | if (uwsgi.sharedareasize > 0) { |
| | 864 | #ifndef __OpenBSD__ |
| | 865 | uwsgi.sharedareamutex = mmap (NULL, sizeof (pthread_mutexattr_t) + sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); |
| | 866 | if (!uwsgi.sharedareamutex) { |
| | 867 | perror ("mmap()"); |
| | 868 | exit (1); |
| | 869 | } |
| | 870 | #else |
| | 871 | fprintf (stderr, "***WARNING*** the sharedarea on OpenBSD is not SMP-safe. Beware of race conditions !!!\n"); |
| | 872 | #endif |
| | 873 | uwsgi.sharedarea = mmap (NULL, uwsgi.page_size * uwsgi.sharedareasize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); |
| | 874 | if (uwsgi.sharedarea) { |
| | 875 | fprintf (stderr, "shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea); |
| | 876 | |
| | 877 | #ifdef __APPLE__ |
| | 878 | memset (uwsgi.sharedareamutex, 0, sizeof (OSSpinLock)); |
| | 879 | #else |
| | 880 | #ifndef __OpenBSD__ |
| | 881 | if (pthread_mutexattr_init ((pthread_mutexattr_t *) uwsgi.sharedareamutex)) { |
| | 882 | fprintf (stderr, "unable to allocate mutexattr structure\n"); |
| | 883 | exit (1); |
| | 884 | } |
| | 885 | if (pthread_mutexattr_setpshared ((pthread_mutexattr_t *) uwsgi.sharedareamutex, PTHREAD_PROCESS_SHARED)) { |
| | 886 | fprintf (stderr, "unable to share mutex\n"); |
| | 887 | exit (1); |
| | 888 | } |
| | 889 | if (pthread_mutex_init ((pthread_mutex_t *) uwsgi.sharedareamutex + sizeof (pthread_mutexattr_t), (pthread_mutexattr_t *) uwsgi.sharedareamutex)) { |
| | 890 | fprintf (stderr, "unable to initialize mutex\n"); |
| | 891 | exit (1); |
| | 892 | } |
| | 893 | #endif |
| | 894 | #endif |
| | 895 | |
| | 896 | } |
| | 897 | else { |
| | 898 | perror ("mmap()"); |
| | 899 | exit (1); |
| | 900 | } |
| | 901 | |
| | 902 | } |
| | 903 | |
| | 904 | init_uwsgi_embedded_module (); |
| | 905 | #endif |
| | 906 | #endif |
| | 907 | |
| | 908 | |
| | 909 | |
| | 910 | #ifdef UWSGI_ONEAPP |
| | 911 | |
| | 912 | |
| | 913 | wi = malloc (sizeof (struct uwsgi_app)); |
| | 914 | if (wi == NULL) { |
| | 915 | perror ("malloc()"); |
| | 916 | exit (1); |
| | 917 | } |
| | 918 | memset (wi, 0, sizeof (struct uwsgi_app)); |
| | 919 | |
| | 920 | // load wsgi module/script |
| | 921 | for (i = optind; i < argc; i++) { |
| | 922 | init_uwsgi_vars (); |
| | 923 | wi->wsgi_module = PyImport_ImportModule (argv[i]); |
| | 924 | if (!wi->wsgi_module) { |
| | 925 | PyErr_Print (); |
| | 926 | exit (1); |
| | 927 | } |
| | 928 | wi->wsgi_dict = PyModule_GetDict (wi->wsgi_module); |
| | 929 | if (!wi->wsgi_dict) { |
| | 930 | PyErr_Print (); |
| | 931 | exit (1); |
| | 932 | } |
| | 933 | wi->wsgi_callable = PyDict_GetItemString (wi->wsgi_dict, "application"); |
| | 934 | if (!wi->wsgi_callable) { |
| | 935 | PyErr_Print (); |
| | 936 | exit (1); |
| | 937 | } |
| | 938 | wi->wsgi_environ = PyDict_New (); |
| | 939 | if (!wi->wsgi_environ) { |
| | 940 | PyErr_Print (); |
| | 941 | exit (1); |
| | 942 | } |
| | 943 | |
| | 944 | wi->wsgi_harakiri = PyDict_GetItemString (wi->wsgi_dict, "harakiri"); |
| | 945 | |
| | 946 | wi->wsgi_args = PyTuple_New (2); |
| | 947 | if (!wi->wsgi_args) { |
| | 948 | PyErr_Print (); |
| | 949 | exit (1); |
| | 950 | } |
| | 951 | if (PyTuple_SetItem (wi->wsgi_args, 0, wi->wsgi_environ)) { |
| | 952 | PyErr_Print (); |
| | 953 | exit (1); |
| | 954 | } |
| | 955 | if (PyTuple_SetItem (wi->wsgi_args, 1, wsgi_spitout)) { |
| | 956 | PyErr_Print (); |
| | 957 | exit (1); |
| | 958 | } |
| | 959 | break; |
| | 960 | } |
| | 961 | |
| | 962 | if (!wi->wsgi_module) { |
| | 963 | fprintf (stderr, "unable to find the wsgi script. Have you specified it ?\n"); |
| | 964 | exit (1); |
| | 965 | } |
| | 966 | #endif |
| | 967 | |
| | 968 | Py_OptimizeFlag = uwsgi.py_optimize; |
| | 969 | |
| | 970 | uwsgi.main_thread = PyThreadState_Get (); |
| | 971 | |
| | 972 | |
| | 973 | #ifdef UWSGI_THREADING |
| | 974 | if (uwsgi.has_threads) { |
| | 975 | PyEval_InitThreads (); |
| | 976 | fprintf (stderr, "threads support enabled\n"); |
| | 977 | } |
| | 978 | |
| | 979 | #endif |
| | 980 | |
| | 981 | if (!no_server) { |
| | 982 | #ifndef UNBIT |
| | 983 | if (uwsgi.socket_name != NULL && !uwsgi.is_a_reload) { |
| | 984 | #ifdef UWSGI_SCTP |
| | 985 | if (!strncmp (uwsgi.socket_name, "sctp:", 5)) { |
| | 986 | char *sctp_port = strchr (uwsgi.socket_name + 5, ':'); |
| | 987 | if (sctp_port == NULL) { |
| | 988 | fprintf (stderr, "invalid SCTP port ! syntax: sctp:ip1,ip2,ipN:port\n"); |
| | 989 | exit (1); |
| | 990 | } |
| | 991 | uwsgi.serverfd = bind_to_sctp (uwsgi.socket_name + 5, uwsgi.listen_queue, sctp_port); |
| | 992 | i_am_sctp = 1; |
| | 993 | } |
| | 994 | else { |
| | 995 | #endif |
| | 996 | char *tcp_port = strchr (uwsgi.socket_name, ':'); |
| | 997 | if (tcp_port == NULL) { |
| | 998 | uwsgi.serverfd = bind_to_unix (uwsgi.socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); |
| | 999 | } |
| | 1000 | else { |
| | 1001 | uwsgi.serverfd = bind_to_tcp (uwsgi.socket_name, uwsgi.listen_queue, tcp_port); |
| | 1002 | } |
| | 1003 | |
| | 1004 | if (uwsgi.serverfd < 0) { |
| | 1005 | fprintf (stderr, "unable to create the server socket.\n"); |
| | 1006 | exit (1); |
| | 1007 | } |
| | 1008 | #ifdef UWSGI_SCTP |
| | 1009 | } |
| | 1010 | #endif |
| | 1011 | } |
| | 1012 | #endif |
| | 1013 | |
| | 1014 | socket_type_len = sizeof (int); |
| | 1015 | if (getsockopt (uwsgi.serverfd, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) { |
| | 1016 | perror ("getsockopt()"); |
| | 1017 | fprintf(stderr, "The -s/--socket option is missing and stdin is not a socket.\n"); |
| | 1018 | exit (1); |
| | 1019 | } |
| | 1020 | |
| | 1021 | } |
| | 1022 | |
| | 1023 | |
| | 1024 | |
| | 1025 | if (uwsgi.single_interpreter == 1) { |
| | 1026 | init_uwsgi_vars (); |
| | 1027 | } |
| | 1028 | |
| | 1029 | memset (uwsgi.wsgi_apps, 0, sizeof (uwsgi.wsgi_apps)); |
| | 1030 | |
| | 1031 | |
| | 1032 | |
| | 1033 | uwsgi.poll.events = POLLIN; |
| | 1034 | |
| | 1035 | memset (&wsgi_req, 0, sizeof (struct wsgi_request)); |
| | 1036 | |
| | 1037 | /* shared area for workers */ |
| | 1038 | uwsgi.workers = (struct uwsgi_worker *) mmap (NULL, sizeof (struct uwsgi_worker) * uwsgi.numproc + 1, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); |
| | 1039 | if (!uwsgi.workers) { |
| | 1040 | perror ("mmap()"); |
| | 1041 | exit (1); |
| | 1042 | } |
| | 1043 | memset (uwsgi.workers, 0, sizeof (struct uwsgi_worker) * uwsgi.numproc + 1); |
| | 1044 | |
| | 1045 | uwsgi.mypid = getpid (); |
| | 1046 | masterpid = uwsgi.mypid; |
| | 1047 | |
| | 1048 | #ifndef UNBIT |
| | 1049 | if (uwsgi.pidfile) { |
| | 1050 | fprintf (stderr, "writing pidfile to %s\n", uwsgi.pidfile); |
| | 1051 | pidfile = fopen (uwsgi.pidfile, "w"); |
| | 1052 | if (!pidfile) { |
| | 1053 | perror ("fopen"); |
| | 1054 | exit (1); |
| | 1055 | } |
| | 1056 | if (fprintf (pidfile, "%d\n", masterpid) < 0) { |
| | 1057 | fprintf (stderr, "could not write pidfile.\n"); |
| | 1058 | } |
| | 1059 | fclose (pidfile); |
| | 1060 | } |
| | 1061 | #endif |
| | 1062 | |
| | 1063 | if (uwsgi.buffer_size > 65536) { |
| | 1064 | fprintf (stderr, "invalid buffer size.\n"); |
| | 1065 | exit (1); |
| | 1066 | } |
| | 1067 | buffer = malloc (uwsgi.buffer_size); |
| | 1068 | if (buffer == NULL) { |
| | 1069 | fprintf (stderr, "unable to allocate memory for buffer.\n"); |
| | 1070 | exit (1); |
| | 1071 | } |
| | 1072 | |
| | 1073 | fprintf (stderr, "request/response buffer (%d bytes) allocated.\n", uwsgi.buffer_size); |
| | 1074 | |
| | 1075 | /* save the masterpid */ |
| | 1076 | uwsgi.workers[0].pid = masterpid; |
| | 1077 | |
| | 1078 | fprintf(stderr,"initializing hooks..."); |
| | 1079 | |
| | 1080 | uwsgi.hooks[0] = uwsgi_request_wsgi ; |
| | 1081 | uwsgi.after_hooks[0] = uwsgi_after_request_wsgi ; |
| | 1082 | |
| | 1083 | uwsgi.hooks[UWSGI_MODIFIER_ADMIN_REQUEST] = uwsgi_request_admin ; //10 |
| | 1084 | #ifdef UWSGI_SPOOLER |
| | 1085 | uwsgi.hooks[UWSGI_MODIFIER_SPOOL_REQUEST] = uwsgi_request_spooler ; //17 |
| | 1086 | #endif |
| | 1087 | uwsgi.hooks[UWSGI_MODIFIER_FASTFUNC] = uwsgi_request_fastfunc ; //26 |
| | 1088 | |
| | 1089 | uwsgi.hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_request_wsgi ; // 30 |
| | 1090 | uwsgi.after_hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_after_request_wsgi; // 30 |
| | 1091 | |
| | 1092 | uwsgi.hooks[UWSGI_MODIFIER_MESSAGE_MARSHAL] = uwsgi_request_marshal ; //33 |
| | 1093 | uwsgi.hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping ; //100 |
| | 1094 | |
| | 1095 | fprintf(stderr,"done.\n"); |
| | 1096 | |
| | 1097 | #ifdef UWSGI_ERLANG |
| | 1098 | if (uwsgi.erlang_node) { |
| | 1099 | uwsgi.erlangfd = init_erlang(uwsgi.erlang_node); |
| | 1100 | } |
| | 1101 | #endif |
| | 1102 | |
| | 1103 | |
| | 1104 | |
| | 1105 | if (uwsgi.wsgi_config != NULL) { |
| | 1106 | uwsgi_wsgi_config (); |
| | 1107 | } |
| | 1108 | #ifdef UWSGI_XML |
| | 1109 | else if (uwsgi.xml_config != NULL) { |
| | 1110 | uwsgi_xml_config (&wsgi_req, NULL); |
| | 1111 | } |
| | 1112 | #endif |
| | 1113 | |
| | 1114 | #ifdef UWSGI_PASTE |
| | 1115 | else if (uwsgi.paste != NULL) { |
| | 1116 | uwsgi_paste_config (); |
| | 1117 | } |
| | 1118 | #endif |
| | 1119 | |
| | 1120 | if (uwsgi.test_module != NULL) { |
| | 1121 | if (PyImport_ImportModule (uwsgi.test_module)) { |
| | 1122 | exit (0); |
| | 1123 | } |
| | 1124 | exit (1); |
| | 1125 | } |
| | 1126 | |
| | 1127 | |
| | 1128 | |
| | 1129 | #ifndef UNBIT |
| | 1130 | #ifndef ROCK_SOLID |
| | 1131 | if (no_server) { |
| | 1132 | fprintf (stderr, "no-server mode requested. Goodbye.\n"); |
| | 1133 | exit (0); |
| | 1134 | } |
| | 1135 | #endif |
| | 1136 | #endif |
| | 1137 | |
| | 1138 | if (!uwsgi.single_interpreter) { |
| | 1139 | fprintf(stderr,"*** uWSGI is running in multiple interpreter mode !!! ***\n"); |
| | 1140 | } |
| | 1141 | |
| | 1142 | /* preforking() */ |
| | 1143 | if (uwsgi.master_process) { |
| | 1144 | if (uwsgi.is_a_reload) { |
| | 1145 | fprintf (stderr, "gracefully (RE)spawned uWSGI master process (pid: %d)\n", uwsgi.mypid); |
| | 1146 | } |
| | 1147 | else { |
| | 1148 | fprintf (stderr, "spawned uWSGI master process (pid: %d)\n", uwsgi.mypid); |
| | 1149 | } |
| | 1150 | } |
| | 1151 | |
| | 1152 | #ifdef UNBIT |
| | 1153 | if (single_app_mode == 1) { |
| | 1154 | wsgi_req.wsgi_script = getenv ("UWSGI_SCRIPT"); |
| | 1155 | if (wsgi_req.wsgi_script) { |
| | 1156 | wsgi_req.wsgi_script_len = strlen (wsgi_req.wsgi_script); |
| | 1157 | } |
| | 1158 | else { |
| | 1159 | fprintf (stderr, "UWSGI_SCRIPT env var not set !\n"); |
| | 1160 | exit (1); |
| | 1161 | } |
| | 1162 | |
| | 1163 | init_uwsgi_app (NULL, NULL); |
| | 1164 | } |
| | 1165 | #endif |
| | 1166 | |
| | 1167 | #ifdef UWSGI_SPOOLER |
| | 1168 | if (spool_dir != NULL) { |
| | 1169 | uwsgi.workers[0].spooler_pid = spooler_start (uwsgi.serverfd, uwsgi_module); |
| | 1170 | } |
| | 1171 | #endif |
| | 1172 | |
| | 1173 | |
| | 1174 | if (!uwsgi.master_process) { |
| | 1175 | if (uwsgi.numproc == 1) { |
| | 1176 | fprintf (stderr, "spawned uWSGI worker 1 (and the only) (pid: %d)\n", masterpid); |
| | 1177 | } |
| | 1178 | else { |
| | 1179 | fprintf (stderr, "spawned uWSGI worker 1 (pid: %d)\n", masterpid); |
| | 1180 | } |
| | 1181 | uwsgi.workers[1].pid = masterpid; |
| | 1182 | uwsgi.workers[1].id = 1; |
| | 1183 | uwsgi.workers[1].last_spawn = time (NULL); |
| | 1184 | uwsgi.workers[1].manage_next_request = 1; |
| | 1185 | #ifdef UWSGI_THREADING |
| | 1186 | uwsgi.workers[1].i_have_gil = 1; |
| | 1187 | #endif |
| | 1188 | uwsgi.mywid = 1; |
| | 1189 | gettimeofday (&last_respawn, NULL); |
| | 1190 | respawn_delta = last_respawn.tv_sec; |
| | 1191 | } |
| | 1192 | |
| | 1193 | |
| | 1194 | for (i = 2-uwsgi.master_process ; i < uwsgi.numproc + 1; i++) { |
| | 1195 | /* let the worker know his worker_id (wid) */ |
| | 1196 | pid = fork (); |
| | 1197 | if (pid == 0) { |
| | 1198 | uwsgi.mypid = getpid (); |
| | 1199 | uwsgi.workers[i].pid = uwsgi.mypid; |
| | 1200 | uwsgi.workers[i].id = i; |
| | 1201 | uwsgi.workers[i].last_spawn = time (NULL); |
| | 1202 | uwsgi.workers[i].manage_next_request = 1; |
| | 1203 | #ifdef UWSGI_THREADING |
| | 1204 | uwsgi.workers[i].i_have_gil = 1; |
| | 1205 | #endif |
| | 1206 | uwsgi.mywid = i; |
| | 1207 | if (uwsgi.serverfd != 0 && uwsgi.master_process == 1) { |
| | 1208 | /* close STDIN for workers */ |
| | 1209 | close (0); |
| | 1210 | } |
| | 1211 | break; |
| | 1212 | } |
| | 1213 | else if (pid < 1) { |
| | 1214 | perror ("fork()"); |
| | 1215 | exit (1); |
| | 1216 | } |
| | 1217 | else { |
| | 1218 | fprintf (stderr, "spawned uWSGI worker %d (pid: %d)\n", i, pid); |
| | 1219 | gettimeofday (&last_respawn, NULL); |
| | 1220 | respawn_delta = last_respawn.tv_sec; |
| | 1221 | } |
| | 1222 | } |
| | 1223 | |
| | 1224 | |
| | 1225 | if (getpid () == masterpid && uwsgi.master_process == 1) { |
| | 1226 | /* route signals to workers... */ |
| | 1227 | signal (SIGHUP, (void *) &grace_them_all); |
| | 1228 | signal (SIGTERM, (void *) &reap_them_all); |
| | 1229 | signal (SIGINT, (void *) &kill_them_all); |
| | 1230 | signal (SIGQUIT, (void *) &kill_them_all); |
| | 1231 | /* used only to avoid human-errors */ |
| | 1232 | #ifndef UNBIT |
| | 1233 | signal (SIGUSR1, (void *) &stats); |
| | 1234 | #endif |
| | 1235 | |
| | 1236 | if (udp_socket) { |
| | 1237 | udp_poll.fd = bind_to_udp (udp_socket); |
| | 1238 | if (udp_poll.fd < 0) { |
| | 1239 | fprintf (stderr, "unable to bind to udp socket. SNMP and cluster management services will be disabled.\n"); |
| | 1240 | } |
| | 1241 | else { |
| | 1242 | fprintf (stderr, "UDP server enabled.\n"); |
| | 1243 | udp_poll.events = POLLIN; |
| | 1244 | } |
| | 1245 | } |
| | 1246 | for (;;) { |
| | 1247 | if (ready_to_die >= uwsgi.numproc && uwsgi.to_hell) { |
| | 1248 | #ifdef UWSGI_SPOOLER |
| | 1249 | if (spool_dir && uwsgi.workers[0].spooler_pid > 0) { |
| | 1250 | kill (uwsgi.workers[0].spooler_pid, SIGKILL); |
| | 1251 | fprintf(stderr,"killed the spooler with pid %d\n", uwsgi.workers[0].spooler_pid); |
| | 1252 | } |
| | 1253 | |
| | 1254 | #endif |
| | 1255 | fprintf (stderr, "goodbye to uWSGI.\n"); |
| | 1256 | exit (0); |
| | 1257 | } |
| | 1258 | if (ready_to_reload >= uwsgi.numproc && uwsgi.to_heaven) { |
| | 1259 | #ifdef UWSGI_SPOOLER |
| | 1260 | if (spool_dir && uwsgi.workers[0].spooler_pid > 0) { |
| | 1261 | kill (uwsgi.workers[0].spooler_pid, SIGKILL); |
| | 1262 | fprintf(stderr,"wait4() the spooler with pid %d...", uwsgi.workers[0].spooler_pid); |
| | 1263 | diedpid = waitpid(uwsgi.workers[0].spooler_pid, &waitpid_status, 0); |
| | 1264 | fprintf(stderr,"done."); |
| | 1265 | } |
| | 1266 | #endif |
| | 1267 | fprintf (stderr, "binary reloading uWSGI...\n"); |
| | 1268 | if (chdir (cwd)) { |
| | 1269 | perror ("chdir()"); |
| | 1270 | exit (1); |
| | 1271 | } |
| | 1272 | /* check fd table (a module can obviosly open some fd on initialization...) */ |
| | 1273 | fprintf (stderr, "closing all fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf (_SC_OPEN_MAX)); |
| | 1274 | for (i = 3; i < sysconf (_SC_OPEN_MAX); i++) { |
| | 1275 | if (i == uwsgi.serverfd) { |
| | 1276 | continue; |
| | 1277 | } |
| | 1278 | close (i); |
| | 1279 | } |
| | 1280 | if (uwsgi.serverfd != 3) { |
| | 1281 | if (dup2 (uwsgi.serverfd, 3) < 0) { |
| | 1282 | perror ("dup2()"); |
| | 1283 | exit (1); |
| | 1284 | } |
| | 1285 | } |
| | 1286 | fprintf (stderr, "running %s\n", uwsgi.binary_path); |
| | 1287 | strcpy (argv[0], uwsgi.binary_path); |
| | 1288 | execve (uwsgi.binary_path, argv, environ); |
| | 1289 | perror ("execve()"); |
| | 1290 | // never here |
| | 1291 | exit (1); |
| | 1292 | } |
| | 1293 | diedpid = waitpid (WAIT_ANY, &waitpid_status, WNOHANG); |
| | 1294 | if (diedpid == -1) { |
| | 1295 | perror ("waitpid()"); |
| | 1296 | /* here is better to reload all the uWSGI stack */ |
| | 1297 | fprintf (stderr, "something horrible happened...\n"); |
| | 1298 | reap_them_all (); |
| | 1299 | exit (1); |
| | 1300 | } |
| | 1301 | else if (diedpid == 0) { |
| | 1302 | /* PLEASE, do not run python threads in the master process, you can potentially destroy the world, |
| | 1303 | we support this for hyperultramegagodprogrammer and systems |
| | 1304 | */ |
| | 1305 | #ifdef UWSGI_THREADING |
| | 1306 | if (uwsgi.has_threads && uwsgi.options[UWSGI_OPTION_THREADS] == 1) { |
| | 1307 | uwsgi._save = PyEval_SaveThread (); |
| | 1308 | uwsgi.workers[uwsgi.mywid].i_have_gil = 0; |
| | 1309 | } |
| | 1310 | #endif |
| | 1311 | /* all processes ok, doing status scan after N seconds */ |
| | 1312 | check_interval.tv_sec = uwsgi.options[UWSGI_OPTION_MASTER_INTERVAL]; |
| | 1313 | if (!check_interval.tv_sec) |
| | 1314 | check_interval.tv_sec = 1; |
| | 1315 | |
| | 1316 | if (udp_socket && udp_poll.fd >= 0) { |
| | 1317 | rlen = poll (&udp_poll, 1, check_interval.tv_sec * 1000); |
| | 1318 | if (rlen < 0) { |
| | 1319 | perror ("poll()"); |
| | 1320 | } |
| | 1321 | else if (rlen > 0) { |
| | 1322 | udp_len = sizeof (udp_client); |
| | 1323 | rlen = recvfrom (udp_poll.fd, buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len); |
| | 1324 | if (rlen < 0) { |
| | 1325 | perror ("recvfrom()"); |
| | 1326 | } |
| | 1327 | else if (rlen > 0) { |
| | 1328 | memset (udp_client_addr, 0, 16); |
| | 1329 | if (inet_ntop (AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) { |
| | 1330 | fprintf (stderr, "received udp packet of %d bytes from %s:%d\n", rlen, udp_client_addr, ntohs (udp_client.sin_port)); |
| | 1331 | if (buffer[0] == 0x30) { |
| | 1332 | manage_snmp (udp_poll.fd, (uint8_t *) buffer, rlen, &udp_client); |
| | 1333 | } |
| | 1334 | } |
| | 1335 | else { |
| | 1336 | perror ("inet_ntop()"); |
| | 1337 | } |
| | 1338 | } |
| | 1339 | } |
| | 1340 | } |
| | 1341 | else { |
| | 1342 | select (0, NULL, NULL, NULL, &check_interval); |
| | 1343 | } |
| | 1344 | working_workers = 0; |
| | 1345 | blocking_workers = 0; |
| | 1346 | #ifdef UWSGI_THREADING |
| | 1347 | if (uwsgi.has_threads && !uwsgi.workers[uwsgi.mywid].i_have_gil) { |
| | 1348 | PyEval_RestoreThread (uwsgi._save); |
| | 1349 | uwsgi.workers[uwsgi.mywid].i_have_gil = 1; |
| | 1350 | } |
| | 1351 | #endif |
| | 1352 | check_interval.tv_sec = uwsgi.options[UWSGI_OPTION_MASTER_INTERVAL]; |
| | 1353 | if (!check_interval.tv_sec) |
| | 1354 | check_interval.tv_sec = 1; |
| | 1355 | for (i = 1; i <= uwsgi.numproc; i++) { |
| | 1356 | /* first check for harakiri */ |
| | 1357 | if (uwsgi.workers[i].harakiri > 0) { |
| | 1358 | if (uwsgi.workers[i].harakiri < time (NULL)) { |
| | 1359 | /* first try to invoke the harakiri() custom handler */ |
| | 1360 | /* TODO */ |
| | 1361 | /* then brutally kill the worker */ |
| | 1362 | kill (uwsgi.workers[i].pid, SIGKILL); |
| | 1363 | } |
| | 1364 | } |
| | 1365 | /* load counters */ |
| | 1366 | if (uwsgi.workers[i].status & UWSGI_STATUS_IN_REQUEST) |
| | 1367 | working_workers++; |
| | 1368 | |
| | 1369 | if (uwsgi.workers[i].status & UWSGI_STATUS_BLOCKING) |
| | 1370 | blocking_workers++; |
| | 1371 | |
| | 1372 | uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time; |
| | 1373 | } |
| | 1374 | |
| | 1375 | continue; |
| | 1376 | |
| | 1377 | } |
| | 1378 | #ifdef UWSGI_SPOOLER |
| | 1379 | /* reload the spooler */ |
| | 1380 | if (spool_dir && uwsgi.workers[0].spooler_pid > 0) { |
| | 1381 | if (diedpid == uwsgi.workers[0].spooler_pid) { |
| | 1382 | fprintf(stderr,"OOOPS the spooler is no more...trying respawn...\n"); |
| | 1383 | uwsgi.workers[0].spooler_pid = spooler_start (uwsgi.serverfd, uwsgi_module); |
| | 1384 | continue; |
| | 1385 | } |
| | 1386 | } |
| | 1387 | #endif |
| | 1388 | /* check for reloading */ |
| | 1389 | if (WIFEXITED (waitpid_status)) { |
| | 1390 | if (WEXITSTATUS (waitpid_status) == UWSGI_RELOAD_CODE && uwsgi.to_heaven) { |
| | 1391 | ready_to_reload++; |
| | 1392 | continue; |
| | 1393 | } |
| | 1394 | else if (WEXITSTATUS (waitpid_status) == UWSGI_END_CODE && uwsgi.to_hell) { |
| | 1395 | ready_to_die++; |
| | 1396 | continue; |
| | 1397 | } |
| | 1398 | } |
| | 1399 | |
| | 1400 | fprintf (stderr, "DAMN ! process %d died :( trying respawn ...\n", diedpid); |
| | 1401 | gettimeofday (&last_respawn, NULL); |
| | 1402 | if (last_respawn.tv_sec == respawn_delta) { |
| | 1403 | fprintf (stderr, "worker respawning too fast !!! i have to sleep a bit...\n"); |
| | 1404 | /* TODO, user configurable fork throttler */ |
| | 1405 | sleep (2); |
| | 1406 | } |
| | 1407 | gettimeofday (&last_respawn, NULL); |
| | 1408 | respawn_delta = last_respawn.tv_sec; |
| | 1409 | uwsgi.mywid = find_worker_id (diedpid); |
| | 1410 | pid = fork (); |
| | 1411 | if (pid == 0) { |
| | 1412 | uwsgi.mypid = getpid (); |
| | 1413 | uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid; |
| | 1414 | uwsgi.workers[uwsgi.mywid].harakiri = 0; |
| | 1415 | uwsgi.workers[uwsgi.mywid].requests = 0; |
| | 1416 | uwsgi.workers[uwsgi.mywid].failed_requests = 0; |
| | 1417 | uwsgi.workers[uwsgi.mywid].respawn_count++; |
| | 1418 | uwsgi.workers[uwsgi.mywid].last_spawn = time (NULL); |
| | 1419 | uwsgi.workers[uwsgi.mywid].manage_next_request = 1; |
| | 1420 | uwsgi.workers[uwsgi.mywid].i_have_gil = 1; |
| | 1421 | break; |
| | 1422 | } |
| | 1423 | else if (pid < 1) { |
| | 1424 | perror ("fork()"); |
| | 1425 | } |
| | 1426 | else { |
| | 1427 | fprintf (stderr, "Respawned uWSGI worker (new pid: %d)\n", pid); |
| | 1428 | #ifdef UWSGI_SPOOLER |
| | 1429 | if (uwsgi.mywid <= 0 && diedpid != uwsgi.workers[0].spooler_pid) { |
| | 1430 | #else |
| | 1431 | if (uwsgi.mywid <= 0) { |
| | 1432 | #endif |
| | 1433 | fprintf (stderr, "warning the died pid was not in the workers list. Probably you hit a BUG of uWSGI\n"); |
| | 1434 | } |
| | 1435 | } |
| | 1436 | } |
| | 1437 | } |
| | 1438 | |
| | 1439 | |
| | 1440 | |
| | 1441 | |
| | 1442 | uwsgi.hvec = malloc (sizeof (struct iovec) * uwsgi.vec_size); |
| | 1443 | if (uwsgi.hvec == NULL) { |
| | 1444 | fprintf (stderr, "unable to allocate memory for iovec.\n"); |
| | 1445 | exit (1); |
| | 1446 | } |
| | 1447 | |
| | 1448 | if (uwsgi.options[UWSGI_OPTION_HARAKIRI] > 0 && !uwsgi.master_process) { |
| | 1449 | signal (SIGALRM, (void *) &harakiri); |
| | 1450 | } |
| | 1451 | |
| | 1452 | /* gracefully reload */ |
| | 1453 | signal (SIGHUP, (void *) &gracefully_kill); |
| | 1454 | /* close the process (useful for master INT) */ |
| | 1455 | signal (SIGINT, (void *) &end_me); |
| | 1456 | /* brutally reload */ |
| | 1457 | signal (SIGTERM, (void *) &reload_me); |
| | 1458 | |
| | 1459 | |
| | 1460 | #ifndef UNBIT |
| | 1461 | signal (SIGUSR1, (void *) &stats); |
| | 1462 | #endif |
| | 1463 | |
| | 1464 | |
| | 1465 | signal (SIGPIPE, (void *) &warn_pipe); |
| | 1466 | |
| | 1467 | |
| | 1468 | #ifdef UWSGI_ERLANG |
| | 1469 | if (uwsgi.erlang_nodes > 0) { |
| | 1470 | if ( (uwsgi.mywid - uwsgi.erlang_nodes) <= (uwsgi.numproc - uwsgi.erlang_nodes)) { |
| | 1471 | erlang_loop(buffer); |
| | 1472 | // NEVER HERE |
| | 1473 | exit(1); |
| | 1474 | } |
| | 1475 | } |
| | 1476 | else { |
| | 1477 | // close the erlang server fd for python workers |
| | 1478 | close(uwsgi.erlangfd); |
| | 1479 | } |
| | 1480 | #endif |
| | 1481 | |
| | 1482 | #ifdef UWSGI_THREADING |
| | 1483 | // release the GIL |
| | 1484 | if (uwsgi.has_threads) { |
| | 1485 | uwsgi._save = PyEval_SaveThread (); |
| | 1486 | uwsgi.workers[uwsgi.mywid].i_have_gil = 0; |
| | 1487 | } |
| | 1488 | #endif |
| | 1489 | |
| | 1490 | |
| | 1491 | while (uwsgi.workers[uwsgi.mywid].manage_next_request) { |
| | 1492 | |
| | 1493 | |
| | 1494 | wsgi_req.app_id = uwsgi.default_app; |
| | 1495 | #ifdef UWSGI_SENDFILE |
| | 1496 | wsgi_req.sendfile_fd = -1; |
| | 1497 | #endif |
| | 1498 | // clear all status bits |
| | 1499 | UWSGI_CLEAR_STATUS ; |
| | 1500 | |
| | 1501 | uwsgi.poll.fd = accept (uwsgi.serverfd, (struct sockaddr *) &c_addr, (socklen_t *) & c_len); |
| | 1502 | |
| | 1503 | if (uwsgi.poll.fd < 0) { |
| | 1504 | perror ("accept()"); |
| | 1505 | continue; |
| | 1506 | } |
| | 1507 | |
| | 1508 | UWSGI_SET_IN_REQUEST; |
| | 1509 | |
| | 1510 | if (uwsgi.options[UWSGI_OPTION_LOGGING]) |
| | 1511 | gettimeofday (&wsgi_req.start_of_request, NULL); |
| | 1512 | |
| | 1513 | |
| | 1514 | |
| | 1515 | #ifdef UWSGI_SCTP |
| | 1516 | if (i_am_sctp == 1) { |
| | 1517 | // get stream id, and map it to uwsgi modifiers |
| | 1518 | struct sctp_status sstatus; |
| | 1519 | memset (&sstatus, 0, sizeof (sstatus)); |
| | 1520 | socklen_t slen = sizeof (sstatus); |
| | 1521 | sstatus.sstat_assoc_id = 1; |
| | 1522 | if (getsockopt (uwsgi.poll.fd, IPPROTO_SCTP, SCTP_STATUS, &sstatus, &slen)) { |
| | 1523 | perror ("getsockopt()"); |
| | 1524 | } |
| | 1525 | |
| | 1526 | memset (&sctp_ss, 0, sizeof (sctp_ss)); |
| | 1527 | |
| | 1528 | fprintf (stderr, "%d %d\n", sstatus.sstat_instrms, sstatus.sstat_outstrms); |
| | 1529 | |
| | 1530 | i = 0; |
| | 1531 | wsgi_req.size = sctp_recvmsg (uwsgi.poll.fd, buffer, uwsgi.buffer_size, 0, 0, &sctp_ss, 0); |
| | 1532 | if (wsgi_req.size < 0) { |
| | 1533 | perror ("sctp_recvmsg()"); |
| | 1534 | } |
| | 1535 | fprintf (stderr, "received uwsgi message of %d bytes on stream id %d flags %d\n", wsgi_req.size, ntohs (sctp_ss.sinfo_stream), i); |
| | 1536 | |
| | 1537 | } |
| | 1538 | else { |
| | 1539 | #endif |
| | 1540 | if (!uwsgi_parse_response (&uwsgi.poll, uwsgi.options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) &wsgi_req, buffer)) { |
| | 1541 | continue; |
| | 1542 | } |
| | 1543 | #ifdef UWSGI_SCTP |
| | 1544 | } |
| | 1545 | #endif |
| | 1546 | |
| | 1547 | // enter harakiri mode |
| | 1548 | if (uwsgi.options[UWSGI_OPTION_HARAKIRI] > 0) { |
| | 1549 | set_harakiri(uwsgi.options[UWSGI_OPTION_HARAKIRI]); |
| | 1550 | } |
| | 1551 | |
| | 1552 | ret = (*uwsgi.hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req, buffer); |
| | 1553 | // calculate execution time |
| | 1554 | gettimeofday(&wsgi_req.end_of_request, NULL) ; |
| | 1555 | uwsgi.workers[uwsgi.mywid].running_time += (double) (( (double)(wsgi_req.end_of_request.tv_sec*1000000+wsgi_req.end_of_request.tv_usec)-(double)(wsgi_req.start_of_request.tv_sec*1000000+wsgi_req.start_of_request.tv_usec))/ (double)1000.0) ; |
| | 1556 | |
| | 1557 | |
| | 1558 | // get memory usage |
| | 1559 | if (uwsgi.options[UWSGI_OPTION_MEMORY_DEBUG] == 1) |
| | 1560 | get_memusage(); |
| | 1561 | |
| | 1562 | // close the connection with the webserver |
| | 1563 | close(uwsgi.poll.fd); |
| | 1564 | uwsgi.workers[0].requests++; |
| | 1565 | uwsgi.workers[uwsgi.mywid].requests++; |
| | 1566 | |
| | 1567 | if (!ret) |
| | 1568 | (*uwsgi.after_hooks[wsgi_req.modifier])(&uwsgi, &wsgi_req, buffer); |
| | 1569 | |
| | 1570 | |
| | 1571 | // leave harakiri mode |
| | 1572 | if (uwsgi.workers[uwsgi.mywid].harakiri > 0) { |
| | 1573 | set_harakiri(0); |
| | 1574 | } |
| | 1575 | |
| | 1576 | |
| | 1577 | // defunct process reaper |
| | 1578 | if (uwsgi.options[UWSGI_OPTION_REAPER] == 1) { |
| | 1579 | waitpid (-1, &waitpid_status, WNOHANG); |
| | 1580 | } |
| | 1581 | // reset request |
| | 1582 | memset (&wsgi_req, 0, sizeof (struct wsgi_request)); |
| | 1583 | #ifdef UNBIT |
| | 1584 | if (tmp_filename && tmp_dir_fd >= 0) { |
| | 1585 | tmp_filename[0] = 0; |
| | 1586 | } |
| | 1587 | #endif |
| | 1588 | |
| | 1589 | if (uwsgi.options[UWSGI_OPTION_MAX_REQUESTS] > 0 && uwsgi.workers[uwsgi.mywid].requests >= uwsgi.options[UWSGI_OPTION_MAX_REQUESTS]) { |
| | 1590 | goodbye_cruel_world (); |
| | 1591 | } |
| | 1592 | |
| | 1593 | #ifdef UNBIT |
| | 1594 | if (check_for_memory_errors) { |
| | 1595 | if (syscall (357, &us, 0) > 0) { |
| | 1596 | if (us.memory_errors > 0) { |
| | 1597 | fprintf (stderr, "Unbit Kernel found a memory allocation error for process %d.\n", uwsgi.mypid); |
| | 1598 | goodbye_cruel_world (); |
| | 1599 | } |
| | 1600 | } |
| | 1601 | } |
| | 1602 | #endif |
| | 1603 | |
| | 1604 | } |
| | 1605 | |
| | 1606 | if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) { |
| | 1607 | reload_me (); |
| | 1608 | } |
| | 1609 | else { |
| | 1610 | goodbye_cruel_world (); |
| | 1611 | } |
| | 1612 | |
| | 1613 | /* never here */ |
| | 1614 | return 0; |
| | 1615 | } |
| | 1616 | |
| | 1617 | void init_uwsgi_vars () { |
| | 1618 | |
| | 1619 | #ifndef UNBIT |
| | 1620 | int i; |
| | 1621 | #endif |
| | 1622 | PyObject *pysys, *pysys_dict, *pypath; |
| | 1623 | |
| | 1624 | /* add cwd to pythonpath */ |
| | 1625 | pysys = PyImport_ImportModule ("sys"); |
| | 1626 | if (!pysys) { |
| | 1627 | PyErr_Print (); |
| | 1628 | exit (1); |
| | 1629 | } |
| | 1630 | pysys_dict = PyModule_GetDict (pysys); |
| | 1631 | pypath = PyDict_GetItemString (pysys_dict, "path"); |
| | 1632 | if (!pypath) { |
| | 1633 | PyErr_Print (); |
| | 1634 | exit (1); |
| | 1635 | } |
| | 1636 | if (PyList_Insert (pypath, 0, PyString_FromString (".")) != 0) { |
| | 1637 | PyErr_Print (); |
| | 1638 | } |
| | 1639 | |
| | 1640 | #ifndef UNBIT |
| | 1641 | for (i = 0; i < uwsgi.python_path_cnt; i++) { |
| | 1642 | if (PyList_Insert (pypath, 0, PyString_FromString (uwsgi.python_path[i])) != 0) { |
| | 1643 | PyErr_Print (); |
| | 1644 | } |
| | 1645 | else { |
| | 1646 | fprintf (stderr, "added %s to pythonpath.\n", uwsgi.python_path[i]); |
| | 1647 | } |
| | 1648 | } |
| | 1649 | #endif |
| | 1650 | |
| | 1651 | } |
| | 1652 | |
| | 1653 | #ifndef ROCK_SOLID |
| | 1654 | int init_uwsgi_app (PyObject * force_wsgi_dict, PyObject * my_callable) { |
| | 1655 | PyObject *wsgi_module, *wsgi_dict = NULL; |
| | 1656 | PyObject *pymain, *zero; |
| | 1657 | PyObject *pycprof, *pycprof_dict; |
| | 1658 | char tmpstring[256]; |
| | 1659 | int id; |
| | 1660 | |
| | 1661 | struct uwsgi_app *wi; |
| | 1662 | |
| | 1663 | memset (tmpstring, 0, 256); |
| | 1664 | |
| | 1665 | |
| | 1666 | if (wsgi_req.wsgi_script_len == 0 && ((wsgi_req.wsgi_module_len == 0 || wsgi_req.wsgi_callable_len == 0) && uwsgi.wsgi_config == NULL && my_callable == NULL)) { |
| | 1667 | fprintf (stderr, "invalid application (%.*s). skip.\n", wsgi_req.script_name_len, wsgi_req.script_name); |
| | 1668 | return -1; |
| | 1669 | } |
| | 1670 | |
| | 1671 | if (uwsgi.wsgi_config && wsgi_req.wsgi_callable_len == 0 && my_callable == NULL) { |
| | 1672 | fprintf (stderr, "invalid application (%.*s). skip.\n", wsgi_req.script_name_len, wsgi_req.script_name); |
| | 1673 | return -1; |
| | 1674 | } |
| | 1675 | |
| | 1676 | if (wsgi_req.wsgi_script_len > 255 || wsgi_req.wsgi_module_len > 255 || wsgi_req.wsgi_callable_len > 255) { |
| | 1677 | fprintf (stderr, "invalid application's string size. skip.\n"); |
| | 1678 | return -1; |
| | 1679 | } |
| | 1680 | |
| | 1681 | id = uwsgi.wsgi_cnt; |
| | 1682 | |
| | 1683 | |
| | 1684 | if (wsgi_req.script_name_len == 0) { |
| | 1685 | wsgi_req.script_name_len = 1; |
| | 1686 | wsgi_req.script_name = (char *) app_slash; |
| | 1687 | id = 0; |
| | 1688 | } |
| | 1689 | else if (wsgi_req.script_name_len == 1) { |
| | 1690 | if (wsgi_req.script_name[0] == '/') { |
| | 1691 | id = 0; |
| | 1692 | } |
| | 1693 | } |
| | 1694 | |
| | 1695 | |
| | 1696 | zero = PyString_FromStringAndSize (wsgi_req.script_name, wsgi_req.script_name_len); |
| | 1697 | if (!zero) { |
| | 1698 | Py_FatalError ("cannot get mountpoint python object !\n"); |
| | 1699 | } |
| | 1700 | |
| | 1701 | if (PyDict_GetItem (uwsgi.py_apps, zero) != NULL) { |
| | 1702 | Py_DECREF (zero); |
| | 1703 | fprintf (stderr, "mountpoint %.*s already configured. skip.\n", wsgi_req.script_name_len, wsgi_req.script_name); |
| | 1704 | return -1; |
| | 1705 | } |
| | 1706 | |
| | 1707 | Py_DECREF (zero); |
| | 1708 | |
| | 1709 | wi = &uwsgi.wsgi_apps[id]; |
| | 1710 | |
| | 1711 | memset (wi, 0, sizeof (struct uwsgi_app)); |
| | 1712 | |
| | 1713 | if (uwsgi.single_interpreter == 0) { |
| | 1714 | wi->interpreter = Py_NewInterpreter (); |
| | 1715 | if (!wi->interpreter) { |
| | 1716 | fprintf (stderr, "unable to initialize the new interpreter\n"); |
| | 1717 | exit (1); |
| | 1718 | } |
| | 1719 | PyThreadState_Swap (wi->interpreter); |
| | 1720 | #ifndef PYTHREE |
| | 1721 | init_uwsgi_embedded_module (); |
| | 1722 | #endif |
| | 1723 | init_uwsgi_vars (); |
| | 1724 | fprintf (stderr, "interpreter for app %d initialized.\n", id); |
| | 1725 | } |
| | 1726 | |
| | 1727 | if (uwsgi.paste) { |
| | 1728 | wi->wsgi_callable = my_callable; |
| | 1729 | Py_INCREF (my_callable); |
| | 1730 | } |
| | 1731 | |
| | 1732 | else { |
| | 1733 | |
| | 1734 | if (uwsgi.wsgi_config == NULL) { |
| | 1735 | if (wsgi_req.wsgi_script_len > 0) { |
| | 1736 | memcpy (tmpstring, wsgi_req.wsgi_script, wsgi_req.wsgi_script_len); |
| | 1737 | wsgi_module = PyImport_ImportModule (tmpstring); |
| | 1738 | if (!wsgi_module) { |
| | 1739 | PyErr_Print (); |
| | 1740 | if (uwsgi.single_interpreter == 0) { |
| | 1741 | Py_EndInterpreter (wi->interpreter); |
| | 1742 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1743 | } |
| | 1744 | return -1; |
| | 1745 | } |
| | 1746 | wsgi_req.wsgi_callable = "application"; |
| | 1747 | wsgi_req.wsgi_callable_len = 11; |
| | 1748 | } |
| | 1749 | else { |
| | 1750 | memcpy (tmpstring, wsgi_req.wsgi_module, wsgi_req.wsgi_module_len); |
| | 1751 | wsgi_module = PyImport_ImportModule (tmpstring); |
| | 1752 | if (!wsgi_module) { |
| | 1753 | PyErr_Print (); |
| | 1754 | if (uwsgi.single_interpreter == 0) { |
| | 1755 | Py_EndInterpreter (wi->interpreter); |
| | 1756 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1757 | } |
| | 1758 | return -1; |
| | 1759 | } |
| | 1760 | } |
| | 1761 | |
| | 1762 | wsgi_dict = PyModule_GetDict (wsgi_module); |
| | 1763 | if (!wsgi_dict) { |
| | 1764 | PyErr_Print (); |
| | 1765 | if (uwsgi.single_interpreter == 0) { |
| | 1766 | Py_EndInterpreter (wi->interpreter); |
| | 1767 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1768 | } |
| | 1769 | return -1; |
| | 1770 | } |
| | 1771 | |
| | 1772 | } |
| | 1773 | else { |
| | 1774 | wsgi_dict = force_wsgi_dict; |
| | 1775 | } |
| | 1776 | |
| | 1777 | |
| | 1778 | memset (tmpstring, 0, 256); |
| | 1779 | memcpy (tmpstring, wsgi_req.wsgi_callable, wsgi_req.wsgi_callable_len); |
| | 1780 | if (my_callable) { |
| | 1781 | wi->wsgi_callable = my_callable; |
| | 1782 | Py_INCREF (my_callable); |
| | 1783 | } |
| | 1784 | else if (wsgi_dict) { |
| | 1785 | wi->wsgi_callable = PyDict_GetItemString (wsgi_dict, tmpstring); |
| | 1786 | } |
| | 1787 | else { |
| | 1788 | return -1; |
| | 1789 | } |
| | 1790 | |
| | 1791 | } |
| | 1792 | |
| | 1793 | |
| | 1794 | if (!wi->wsgi_callable) { |
| | 1795 | PyErr_Print (); |
| | 1796 | if (uwsgi.single_interpreter == 0) { |
| | 1797 | Py_EndInterpreter (wi->interpreter); |
| | 1798 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1799 | } |
| | 1800 | return -1; |
| | 1801 | } |
| | 1802 | |
| | 1803 | |
| | 1804 | wi->wsgi_environ = PyDict_New (); |
| | 1805 | if (!wi->wsgi_environ) { |
| | 1806 | PyErr_Print (); |
| | 1807 | if (uwsgi.single_interpreter == 0) { |
| | 1808 | Py_EndInterpreter (wi->interpreter); |
| | 1809 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1810 | } |
| | 1811 | return -1; |
| | 1812 | } |
| | 1813 | |
| | 1814 | if (wsgi_dict) { |
| | 1815 | wi->wsgi_harakiri = PyDict_GetItemString (wsgi_dict, "harakiri"); |
| | 1816 | if (wi->wsgi_harakiri) { |
| | 1817 | fprintf (stderr, "initialized Harakiri custom handler: %p.\n", wi->wsgi_harakiri); |
| | 1818 | } |
| | 1819 | } |
| | 1820 | |
| | 1821 | |
| | 1822 | |
| | 1823 | #ifdef UWSGI_PROFILER |
| | 1824 | if (uwsgi.enable_profiler) { |
| | 1825 | pymain = PyImport_AddModule ("__main__"); |
| | 1826 | if (!pymain) { |
| | 1827 | PyErr_Print (); |
| | 1828 | exit (1); |
| | 1829 | } |
| | 1830 | wi->pymain_dict = PyModule_GetDict (pymain); |
| | 1831 | if (!wi->pymain_dict) { |
| | 1832 | PyErr_Print (); |
| | 1833 | exit (1); |
| | 1834 | } |
| | 1835 | if (PyDict_SetItem (wi->pymain_dict, PyString_FromFormat ("uwsgi_application__%d", id), wi->wsgi_callable)) { |
| | 1836 | PyErr_Print (); |
| | 1837 | exit (1); |
| | 1838 | } |
| | 1839 | if (PyDict_SetItem (wi->pymain_dict, PyString_FromFormat ("uwsgi_environ__%d", id), wi->wsgi_environ)) { |
| | 1840 | PyErr_Print (); |
| | 1841 | exit (1); |
| | 1842 | } |
| | 1843 | if (PyDict_SetItem (wi->pymain_dict, PyString_FromFormat ("uwsgi_spit__%d", id), wsgi_spitout)) { |
| | 1844 | PyErr_Print (); |
| | 1845 | exit (1); |
| | 1846 | } |
| | 1847 | |
| | 1848 | pycprof = PyImport_ImportModule ("cProfile"); |
| | 1849 | if (!pycprof) { |
| | 1850 | PyErr_Print (); |
| | 1851 | fprintf (stderr, "trying old profile module... "); |
| | 1852 | pycprof = PyImport_ImportModule ("profile"); |
| | 1853 | if (!pycprof) { |
| | 1854 | fprintf (stderr, "doh!!!\n"); |
| | 1855 | PyErr_Print (); |
| | 1856 | exit (1); |
| | 1857 | } |
| | 1858 | else { |
| | 1859 | fprintf (stderr, "ok and set stdout to linebuf mode.\n"); |
| | 1860 | } |
| | 1861 | } |
| | 1862 | pycprof_dict = PyModule_GetDict (pycprof); |
| | 1863 | if (!pycprof_dict) { |
| | 1864 | PyErr_Print (); |
| | 1865 | exit (1); |
| | 1866 | } |
| | 1867 | wi->wsgi_cprofile_run = PyDict_GetItemString (pycprof_dict, "run"); |
| | 1868 | if (!wi->wsgi_cprofile_run) { |
| | 1869 | PyErr_Print (); |
| | 1870 | exit (1); |
| | 1871 | } |
| | 1872 | |
| | 1873 | wi->wsgi_args = PyTuple_New (1); |
| | 1874 | if (PyTuple_SetItem (wi->wsgi_args, 0, PyString_FromFormat ("uwsgi_out = uwsgi_application__%d(uwsgi_environ__%d,uwsgi_spit__%d)", id, id, id))) { |
| | 1875 | PyErr_Print (); |
| | 1876 | if (uwsgi.single_interpreter == 0) { |
| | 1877 | Py_EndInterpreter (wi->interpreter); |
| | 1878 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1879 | } |
| | 1880 | return -1; |
| | 1881 | } |
| | 1882 | } |
| | 1883 | else { |
| | 1884 | #endif |
| | 1885 | wi->wsgi_args = PyTuple_New (2); |
| | 1886 | if (PyTuple_SetItem (wi->wsgi_args, 0, wi->wsgi_environ)) { |
| | 1887 | PyErr_Print (); |
| | 1888 | if (uwsgi.single_interpreter == 0) { |
| | 1889 | Py_EndInterpreter (wi->interpreter); |
| | 1890 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1891 | } |
| | 1892 | return -1; |
| | 1893 | } |
| | 1894 | if (PyTuple_SetItem (wi->wsgi_args, 1, wsgi_spitout)) { |
| | 1895 | PyErr_Print (); |
| | 1896 | if (uwsgi.single_interpreter == 0) { |
| | 1897 | Py_EndInterpreter (wi->interpreter); |
| | 1898 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1899 | } |
| | 1900 | return -1; |
| | 1901 | } |
| | 1902 | #ifdef UWSGI_PROFILER |
| | 1903 | } |
| | 1904 | #endif |
| | 1905 | |
| | 1906 | #ifdef UWSGI_SENDFILE |
| | 1907 | // prepare sendfile() |
| | 1908 | wi->wsgi_sendfile = PyCFunction_New (uwsgi_sendfile_method, NULL); |
| | 1909 | #endif |
| | 1910 | |
| | 1911 | if (uwsgi.single_interpreter == 0) { |
| | 1912 | PyThreadState_Swap (uwsgi.main_thread); |
| | 1913 | } |
| | 1914 | |
| | 1915 | memset (tmpstring, 0, 256); |
| | 1916 | memcpy (tmpstring, wsgi_req.script_name, wsgi_req.script_name_len); |
| | 1917 | PyDict_SetItemString (uwsgi.py_apps, tmpstring, PyInt_FromLong (id)); |
| | 1918 | PyErr_Print (); |
| | 1919 | |
| | 1920 | fprintf (stderr, "application %d (%s) ready\n", id, tmpstring); |
| | 1921 | |
| | 1922 | if (id == 0) { |
| | 1923 | fprintf (stderr, "setting default application to 0\n"); |
| | 1924 | uwsgi.default_app = 0; |
| | 1925 | } |
| | 1926 | else { |
| | 1927 | uwsgi.wsgi_cnt++; |
| | 1928 | } |
| | 1929 | |
| | 1930 | return id; |
| | 1931 | } |
| | 1932 | |
| | 1933 | #ifdef UWSGI_PASTE |
| | 1934 | void uwsgi_paste_config () { |
| | 1935 | PyObject *paste_module, *paste_dict, *paste_loadapp; |
| | 1936 | PyObject *paste_arg, *paste_app; |
| | 1937 | |
| | 1938 | fprintf (stderr, "Loading paste environment: %s\n", uwsgi.paste); |
| | 1939 | paste_module = PyImport_ImportModule ("paste.deploy"); |
| | 1940 | if (!paste_module) { |
| | 1941 | PyErr_Print (); |
| | 1942 | exit (1); |
| | 1943 | } |
| | 1944 | |
| | 1945 | paste_dict = PyModule_GetDict (paste_module); |
| | 1946 | if (!paste_dict) { |
| | 1947 | PyErr_Print (); |
| | 1948 | exit (1); |
| | 1949 | } |
| | 1950 | |
| | 1951 | paste_loadapp = PyDict_GetItemString (paste_dict, "loadapp"); |
| | 1952 | if (!paste_loadapp) { |
| | 1953 | PyErr_Print (); |
| | 1954 | exit (1); |
| | 1955 | } |
| | 1956 | |
| | 1957 | paste_arg = PyTuple_New (1); |
| | 1958 | if (!paste_arg) { |
| | 1959 | PyErr_Print (); |
| | 1960 | exit (1); |
| | 1961 | } |
| | 1962 | |
| | 1963 | if (PyTuple_SetItem (paste_arg, 0, PyString_FromString (uwsgi.paste))) { |
| | 1964 | PyErr_Print (); |
| | 1965 | exit (1); |
| | 1966 | } |
| | 1967 | |
| | 1968 | paste_app = PyEval_CallObject (paste_loadapp, paste_arg); |
| | 1969 | if (!paste_app) { |
| | 1970 | PyErr_Print (); |
| | 1971 | exit (1); |
| | 1972 | } |
| | 1973 | |
| | 1974 | init_uwsgi_app (NULL, paste_app); |
| | 1975 | } |
| | 1976 | |
| | 1977 | #endif |
| | 1978 | |
| | 1979 | void uwsgi_wsgi_config () { |
| | 1980 | |
| | 1981 | PyObject *wsgi_module, *wsgi_dict; |
| | 1982 | #ifndef PYTHREE |
| | 1983 | PyObject *uwsgi_module, *uwsgi_dict; |
| | 1984 | #endif |
| | 1985 | PyObject *applications; |
| | 1986 | PyObject *app_list; |
| | 1987 | int ret ; |
| | 1988 | Py_ssize_t i; |
| | 1989 | PyObject *app_mnt, *app_app; |
| | 1990 | |
| | 1991 | wsgi_module = PyImport_ImportModule (uwsgi.wsgi_config); |
| | 1992 | if (!wsgi_module) { |
| | 1993 | PyErr_Print (); |
| | 1994 | exit (1); |
| | 1995 | } |
| | 1996 | |
| | 1997 | wsgi_dict = PyModule_GetDict (wsgi_module); |
| | 1998 | if (!wsgi_dict) { |
| | 1999 | PyErr_Print (); |
| | 2000 | exit (1); |
| | 2001 | } |
| | 2002 | |
| | 2003 | fprintf (stderr, "...getting the applications list from the '%s' module...\n", uwsgi.wsgi_config); |
| | 2004 | |
| | 2005 | #ifndef PYTHREE |
| | 2006 | uwsgi_module = PyImport_ImportModule ("uwsgi"); |
| | 2007 | if (!uwsgi_module) { |
| | 2008 | PyErr_Print (); |
| | 2009 | exit (1); |
| | 2010 | } |
| | 2011 | |
| | 2012 | uwsgi_dict = PyModule_GetDict (uwsgi_module); |
| | 2013 | if (!uwsgi_dict) { |
| | 2014 | PyErr_Print (); |
| | 2015 | exit (1); |
| | 2016 | } |
| | 2017 | |
| | 2018 | |
| | 2019 | |
| | 2020 | applications = PyDict_GetItemString (uwsgi_dict, "applications"); |
| | 2021 | if (!PyDict_Check (applications)) { |
| | 2022 | fprintf (stderr, "uwsgi.applications dictionary is not defined, trying with the (deprecated) \"applications\" one...\n"); |
| | 2023 | #endif |
| | 2024 | applications = PyDict_GetItemString (wsgi_dict, "applications"); |
| | 2025 | if (!applications) { |
| | 2026 | fprintf (stderr, "applications dictionary is not defined, trying with the \"application\" callable.\n"); |
| | 2027 | app_app = PyDict_GetItemString (wsgi_dict, "application"); |
| | 2028 | if (app_app) { |
| | 2029 | applications = PyDict_New (); |
| | 2030 | if (!applications) { |
| | 2031 | fprintf (stderr, "could not initialize applications dictionary\n"); |
| | 2032 | exit (1); |
| | 2033 | } |
| | 2034 | if (PyDict_SetItemString (applications, "/", app_app)) { |
| | 2035 | PyErr_Print (); |
| | 2036 | fprintf (stderr, "unable to set default application\n"); |
| | 2037 | exit (1); |
| | 2038 | } |
| | 2039 | } |
| | 2040 | else { |
| | 2041 | fprintf (stderr, "static applications not defined, you have to used the dynamic one...\n"); |
| | 2042 | return; |
| | 2043 | } |
| | 2044 | } |
| | 2045 | #ifndef PYTHREE |
| | 2046 | } |
| | 2047 | #endif |
| | 2048 | |
| | 2049 | if (!PyDict_Check (applications)) { |
| | 2050 | fprintf (stderr, "The 'applications' object must be a dictionary.\n"); |
| | 2051 | exit (1); |
| | 2052 | } |
| | 2053 | |
| | 2054 | app_list = PyDict_Keys (applications); |
| | 2055 | if (!app_list) { |
| | 2056 | PyErr_Print (); |
| | 2057 | exit (1); |
| | 2058 | } |
| | 2059 | if (PyList_Size (app_list) < 1) { |
| | 2060 | fprintf (stderr, "You must define an app.\n"); |
| | 2061 | exit (1); |
| | 2062 | } |
| | 2063 | |
| | 2064 | for (i = 0; i < PyList_Size (app_list); i++) { |
| | 2065 | app_mnt = PyList_GetItem (app_list, i); |
| | 2066 | |
| | 2067 | if (!PyString_Check (app_mnt)) { |
| | 2068 | fprintf (stderr, "the app mountpoint must be a string.\n"); |
| | 2069 | exit (1); |
| | 2070 | } |
| | 2071 | |
| | 2072 | wsgi_req.script_name = PyString_AsString (app_mnt); |
| | 2073 | wsgi_req.script_name_len = strlen (wsgi_req.script_name); |
| | 2074 | |
| | 2075 | app_app = PyDict_GetItem (applications, app_mnt); |
| | 2076 | |
| | 2077 | if (!PyString_Check (app_app) && !PyFunction_Check (app_app) && !PyCallable_Check (app_app)) { |
| | 2078 | fprintf (stderr, "the app callable must be a string, a function or a callable. (found %s)\n", app_app->ob_type->tp_name); |
| | 2079 | exit (1); |
| | 2080 | } |
| | 2081 | |
| | 2082 | if (PyString_Check (app_app)) { |
| | 2083 | wsgi_req.wsgi_callable = PyString_AsString (app_app); |
| | 2084 | wsgi_req.wsgi_callable_len = strlen (wsgi_req.wsgi_callable); |
| | 2085 | fprintf (stderr, "initializing [%s => %s] app...\n", wsgi_req.script_name, wsgi_req.wsgi_callable); |
| | 2086 | ret = init_uwsgi_app (wsgi_dict, NULL); |
| | 2087 | } |
| | 2088 | else { |
| | 2089 | fprintf (stderr, "initializing [%s] app...\n", wsgi_req.script_name); |
| | 2090 | ret = init_uwsgi_app (wsgi_dict, app_app); |
| | 2091 | } |
| | 2092 | |
| | 2093 | if (ret < 0) { |
| | 2094 | fprintf (stderr, "...goodbye cruel world...\n"); |
| | 2095 | exit (1); |
| | 2096 | } |
| | 2097 | Py_DECREF (app_mnt); |
| | 2098 | Py_DECREF (app_app); |
| | 2099 | } |
| | 2100 | |
| | 2101 | } |
| | 2102 | |
| | 2103 | #endif |
| | 2104 | |
| | 2105 | #ifdef UNBIT |
| | 2106 | int uri_to_hex () { |
| | 2107 | int i = 0, j = 0; |
| | 2108 | |
| | 2109 | if (wsgi_req.uri_len < 1) { |
| | 2110 | return 0; |
| | 2111 | } |
| | 2112 | |
| | 2113 | if (wsgi_req.uri_len * 2 > 8192) { |
| | 2114 | return 0; |
| | 2115 | } |
| | 2116 | |
| | 2117 | for (i = 0; i < wsgi_req.uri_len; i++) { |
| | 2118 | sprintf (tmp_filename + j, "%02X", wsgi_req.uri[i]); |
| | 2119 | j += 2; |
| | 2120 | } |
| | 2121 | |
| | 2122 | return j; |
| | 2123 | } |
| | 2124 | #endif |
| | 2125 | |
| | 2126 | #ifdef UWSGI_EMBEDDED |
| | 2127 | void init_uwsgi_embedded_module () { |
| | 2128 | PyObject *new_uwsgi_module, *zero; |
| | 2129 | int i; |
| | 2130 | |
| | 2131 | /* initialize for stats */ |
| | 2132 | uwsgi.workers_tuple = PyTuple_New (uwsgi.numproc); |
| | 2133 | for (i = 0; i < uwsgi.numproc; i++) { |
| | 2134 | zero = PyDict_New (); |
| | 2135 | Py_INCREF (zero); |
| | 2136 | PyTuple_SetItem (uwsgi.workers_tuple, i, zero); |
| | 2137 | } |
| | 2138 | |
| | 2139 | |
| | 2140 | |
| | 2141 | new_uwsgi_module = Py_InitModule ("uwsgi", null_methods); |
| | 2142 | if (new_uwsgi_module == NULL) { |
| | 2143 | fprintf (stderr, "could not initialize the uwsgi python module\n"); |
| | 2144 | exit (1); |
| | 2145 | } |
| | 2146 | |
| | 2147 | uwsgi.embedded_dict = PyModule_GetDict (new_uwsgi_module); |
| | 2148 | if (!uwsgi.embedded_dict) { |
| | 2149 | fprintf (stderr, "could not get uwsgi module __dict__\n"); |
| | 2150 | exit (1); |
| | 2151 | } |
| | 2152 | |
| | 2153 | if (PyDict_SetItemString (uwsgi.embedded_dict, "SPOOL_RETRY", PyInt_FromLong (17))) { |
| | 2154 | PyErr_Print (); |
| | 2155 | exit (1); |
| | 2156 | } |
| | 2157 | |
| | 2158 | if (PyDict_SetItemString (uwsgi.embedded_dict, "numproc", PyInt_FromLong (uwsgi.numproc))) { |
| | 2159 | PyErr_Print (); |
| | 2160 | exit (1); |
| | 2161 | } |
| | 2162 | |
| | 2163 | #ifdef UNBIT |
| | 2164 | if (PyDict_SetItemString (uwsgi.embedded_dict, "unbit", Py_True)) { |
| | 2165 | #else |
| | 2166 | if (PyDict_SetItemString (uwsgi.embedded_dict, "unbit", Py_None)) { |
| | 2167 | #endif |
| | 2168 | PyErr_Print (); |
| | 2169 | exit (1); |
| | 2170 | } |
| | 2171 | |
| | 2172 | if (PyDict_SetItemString (uwsgi.embedded_dict, "buffer_size", PyInt_FromLong (uwsgi.buffer_size))) { |
| | 2173 | PyErr_Print (); |
| | 2174 | exit (1); |
| | 2175 | } |
| | 2176 | |
| | 2177 | if (PyDict_SetItemString (uwsgi.embedded_dict, "started_on", PyInt_FromLong (uwsgi.start_tv.tv_sec))) { |
| | 2178 | PyErr_Print (); |
| | 2179 | exit (1); |
| | 2180 | } |
| | 2181 | |
| | 2182 | if (PyDict_SetItemString (uwsgi.embedded_dict, "start_response", wsgi_spitout)) { |
| | 2183 | PyErr_Print (); |
| | 2184 | exit (1); |
| | 2185 | } |
| | 2186 | |
| | 2187 | if (PyDict_SetItemString (uwsgi.embedded_dict, "fastfuncs", PyList_New (256))) { |
| | 2188 | PyErr_Print (); |
| | 2189 | exit (1); |
| | 2190 | } |
| | 2191 | |
| | 2192 | |
| | 2193 | if (PyDict_SetItemString (uwsgi.embedded_dict, "applist", uwsgi.py_apps)) { |
| | 2194 | PyErr_Print (); |
| | 2195 | exit (1); |
| | 2196 | } |
| | 2197 | |
| | 2198 | if (PyDict_SetItemString (uwsgi.embedded_dict, "applications", Py_None)) { |
| | 2199 | PyErr_Print (); |
| | 2200 | exit (1); |
| | 2201 | } |
| | 2202 | |
| | 2203 | uwsgi.embedded_args = PyTuple_New (2); |
| | 2204 | if (!uwsgi.embedded_args) { |
| | 2205 | PyErr_Print (); |
| | 2206 | exit (1); |
| | 2207 | } |
| | 2208 | |
| | 2209 | if (PyDict_SetItemString (uwsgi.embedded_dict, "message_manager_marshal", Py_None)) { |
| | 2210 | PyErr_Print (); |
| | 2211 | exit (1); |
| | 2212 | } |
| | 2213 | |
| | 2214 | uwsgi.fastfuncslist = PyDict_GetItemString (uwsgi.embedded_dict, "fastfuncs"); |
| | 2215 | if (!uwsgi.fastfuncslist) { |
| | 2216 | PyErr_Print (); |
| | 2217 | exit (1); |
| | 2218 | } |
| | 2219 | |
| | 2220 | init_uwsgi_module_advanced (new_uwsgi_module); |
| | 2221 | |
| | 2222 | #ifdef UWSGI_SPOOLER |
| | 2223 | if (spool_dir != NULL) { |
| | 2224 | init_uwsgi_module_spooler (new_uwsgi_module); |
| | 2225 | } |
| | 2226 | #endif |
| | 2227 | |
| | 2228 | |
| | 2229 | if (uwsgi.sharedareasize > 0 && uwsgi.sharedarea) { |
| | 2230 | init_uwsgi_module_sharedarea (new_uwsgi_module); |
| | 2231 | } |
| | 2232 | } |
| | 2233 | #endif |
| | 2234 | |
| | 2235 | #ifdef UWSGI_SPOOLER |
| | 2236 | pid_t spooler_start (int serverfd, PyObject * uwsgi_module) { |
| | 2237 | pid_t pid; |
| | 2238 | |
| | 2239 | pid = fork (); |
| | 2240 | if (pid < 0) { |
| | 2241 | perror ("fork()"); |
| | 2242 | exit (1); |
| | 2243 | } |
| | 2244 | else if (pid == 0) { |
| | 2245 | close (serverfd); |
| | 2246 | spooler (uwsgi_module); |
| | 2247 | } |
| | 2248 | else if (pid > 0) { |
| | 2249 | fprintf (stderr, "spawned the uWSGI spooler on dir %s with pid %d\n", spool_dir, pid); |
| | 2250 | } |
| | 2251 | |
| | 2252 | return pid; |
| | 2253 | } |
| | 2254 | #endif |
| | 2255 | |
| | 2256 | void manage_opt(int i, char *optarg) { |
| | 2257 | |
| 942 | | #ifndef UNBIT |
| 943 | | #ifndef ROCK_SOLID |
| 944 | | if (uwsgi.options[UWSGI_OPTION_CGI_MODE] == 0) { |
| 945 | | #endif |
| 946 | | #endif |
| 947 | | if (uwsgi.test_module == NULL) { |
| 948 | | fprintf (stderr, "*** Starting uWSGI (%dbit) on [%.*s] ***\n", (int) (sizeof (void *)) * 8, 24, ctime ((const time_t *) &uwsgi.start_tv.tv_sec)); |
| 949 | | } |
| 950 | | #ifndef UNBIT |
| 951 | | #ifndef ROCK_SOLID |
| 952 | | } |
| 953 | | else { |
| 954 | | fprintf (stderr, "*** Starting uWSGI (CGI mode) (%dbit) on [%.*s] ***\n", (int) (sizeof (void *)) * 8, 24, ctime ((const time_t *) &uwsgi.start_tv.tv_sec)); |
| 955 | | } |
| 956 | | #endif |
| 957 | | #endif |
| 958 | | |
| 959 | | #ifdef __BIG_ENDIAN__ |
| 960 | | fprintf (stderr, "*** big endian arch detected ***\n"); |
| 961 | | #endif |
| 962 | | |
| 963 | | #ifdef PYTHREE |
| 964 | | fprintf (stderr, "*** Warning Python3.x support is experimental, do not use it in production environment ***\n"); |
| 965 | | #endif |
| 966 | | |
| 967 | | fprintf (stderr, "Python version: %s\n", Py_GetVersion ()); |
| 968 | | |
| 969 | | #ifndef UNBIT |
| 970 | | if (!getuid ()) { |
| 971 | | fprintf (stderr, "uWSGI running as root, you can use --uid/--gid/--chroot options\n"); |
| 972 | | if (uwsgi.chroot) { |
| 973 | | fprintf (stderr, "chroot() to %s\n", uwsgi.chroot); |
| 974 | | if (chroot (uwsgi.chroot)) { |
| 975 | | perror ("chroot()"); |
| 976 | | exit (1); |
| 977 | | } |
| 978 | | #ifdef __linux__ |
| 979 | | if (uwsgi.options[UWSGI_OPTION_MEMORY_DEBUG]) { |
| 980 | | fprintf (stderr, "*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n"); |
| 981 | | } |
| 982 | | #endif |
| 983 | | } |
| 984 | | if (uwsgi.gid) { |
| 985 | | fprintf (stderr, "setgid() to %d\n", uwsgi.gid); |
| 986 | | if (setgid (uwsgi.gid)) { |
| 987 | | perror ("setgid()"); |
| 988 | | exit (1); |
| 989 | | } |
| 990 | | } |
| 991 | | if (uwsgi.uid) { |
| 992 | | fprintf (stderr, "setuid() to %d\n", uwsgi.uid); |
| 993 | | if (setuid (uwsgi.uid)) { |
| 994 | | perror ("setuid()"); |
| 995 | | exit (1); |
| 996 | | } |
| 997 | | } |
| 998 | | |
| 999 | | if (!getuid()) { |
| 1000 | | fprintf(stderr," *** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** \n"); |
| 1001 | | } |
| 1002 | | } |
| 1003 | | else { |
| 1004 | | if (uwsgi.chroot) { |
| 1005 | | fprintf (stderr, "cannot chroot() as non-root user\n"); |
| 1006 | | exit (1); |
| 1007 | | } |
| 1008 | | if (uwsgi.gid) { |
| 1009 | | fprintf (stderr, "cannot setgid() as non-root user\n"); |
| 1010 | | exit (1); |
| 1011 | | } |
| 1012 | | if (uwsgi.uid) { |
| 1013 | | fprintf (stderr, "cannot setuid() as non-root user\n"); |
| 1014 | | exit (1); |
| 1015 | | } |
| 1016 | | } |
| 1017 | | |
| 1018 | | |
| 1019 | | |
| 1020 | | #endif |
| 1021 | | |
| 1022 | | #ifndef UNBIT |
| 1023 | | if (rl.rlim_max > 0) { |
| 1024 | | fprintf (stderr, "limiting address space of processes...\n"); |
| 1025 | | if (setrlimit (RLIMIT_AS, &rl)) { |
| 1026 | | perror ("setrlimit()"); |
| 1027 | | } |
| 1028 | | } |
| 1029 | | #endif |
| 1030 | | |
| 1031 | | if (!getrlimit (RLIMIT_AS, &rl)) { |
| 1032 | | #ifndef UNBIT |
| 1033 | | // check for overflow |
| 1034 | | if ((sizeof (void *) == 4 && (uint32_t) rl.rlim_max < UINT32_MAX) || (sizeof (void *) == 8 && (uint64_t) rl.rlim_max < UINT64_MAX)) { |
| 1035 | | #endif |
| 1036 | | fprintf (stderr, "your process address space limit is %lld bytes (%lld MB)\n", (long long) rl.rlim_max, (long long) rl.rlim_max / 1024 / 1024); |
| 1037 | | #ifndef UNBIT |
| 1038 | | } |
| 1039 | | #endif |
| 1040 | | } |
| 1041 | | |
| 1042 | | uwsgi.page_size = getpagesize (); |
| 1043 | | fprintf (stderr, "your memory page size is %d bytes\n", uwsgi.page_size); |
| 1044 | | |
| 1045 | | #ifndef UNBIT |
| 1046 | | fprintf (stderr, "your server socket listen backlog is limited to %d connections\n", uwsgi.listen_queue); |
| 1047 | | #endif |
| 1048 | | |
| 1049 | | if (uwsgi.synclog) { |
| 1050 | | fprintf (stderr, "allocating a memory page for synced logging.\n"); |
| 1051 | | uwsgi.sync_page = malloc (uwsgi.page_size); |
| 1052 | | if (!uwsgi.sync_page) { |
| 1053 | | perror ("malloc()"); |
| 1054 | | exit (1); |
| 1055 | | } |
| 1056 | | } |
| 1057 | | |
| 1058 | | if (uwsgi.pyhome != NULL) { |
| 1059 | | fprintf (stderr, "Setting PythonHome to %s...\n", uwsgi.pyhome); |
| 1060 | | #ifdef PYTHREE |
| 1061 | | wchar_t *wpyhome; |
| 1062 | | wpyhome = malloc ((sizeof (wchar_t) * strlen (uwsgi.pyhome)) + 2); |
| 1063 | | if (!wpyhome) { |
| 1064 | | perror ("malloc()"); |
| 1065 | | exit (1); |
| 1066 | | } |
| 1067 | | mbstowcs (wpyhome, uwsgi.pyhome, strlen (uwsgi.pyhome)); |
| 1068 | | Py_SetPythonHome (wpyhome); |
| 1069 | | free (wpyhome); |
| 1070 | | #else |
| 1071 | | Py_SetPythonHome (uwsgi.pyhome); |
| 1072 | | #endif |
| 1073 | | } |
| 1074 | | |
| 1075 | | |
| 1076 | | |
| 1077 | | |
| 1078 | | #ifdef PYTHREE |
| 1079 | | wchar_t pname[6]; |
| 1080 | | mbstowcs (pname, "uWSGI", 6); |
| 1081 | | Py_SetProgramName (pname); |
| 1082 | | #else |
| 1083 | | Py_SetProgramName ("uWSGI"); |
| 1084 | | #endif |
| 1085 | | |
| 1086 | | |
| 1087 | | Py_Initialize (); |
| 1088 | | |
| 1089 | | pyargv[0] = "uwsgi"; |
| 1090 | | |
| 1091 | | if (uwsgi.pyargv != NULL) { |
| 1092 | | char *ap; |
| 1093 | | while ((ap = strsep (&uwsgi.pyargv, " \t")) != NULL) { |
| 1094 | | if (*ap != '\0') { |
| 1095 | | pyargv[pyargc] = ap; |
| 1096 | | pyargc++; |
| 1097 | | } |
| 1098 | | if (pyargc + 1 > MAX_PYARGV) |
| 1099 | | break; |
| 1100 | | } |
| 1101 | | } |
| 1102 | | |
| 1103 | | PySys_SetArgv (pyargc, pyargv); |
| 1104 | | |
| 1105 | | |
| 1106 | | #ifndef ROCK_SOLID |
| 1107 | | uwsgi.py_apps = PyDict_New (); |
| 1108 | | if (!uwsgi.py_apps) { |
| 1109 | | PyErr_Print (); |
| 1110 | | exit (1); |
| 1111 | | } |
| 1112 | | |
| 1113 | | #endif |
| 1114 | | |
| 1115 | | |
| 1116 | | wsgi_spitout = PyCFunction_New (uwsgi_spit_method, NULL); |
| 1117 | | wsgi_writeout = PyCFunction_New (uwsgi_write_method, NULL); |
| 1118 | | |
| 1119 | | #ifndef PYTHREE |
| 1120 | | #ifndef ROCK_SOLID |
| 1121 | | uwsgi_module = Py_InitModule ("uwsgi", null_methods); |
| 1122 | | if (uwsgi_module == NULL) { |
| 1123 | | fprintf (stderr, "could not initialize the uwsgi python module\n"); |
| 1124 | | exit (1); |
| 1125 | | } |
| 1126 | | if (uwsgi.sharedareasize > 0) { |
| 1127 | | #ifndef __OpenBSD__ |
| 1128 | | uwsgi.sharedareamutex = mmap (NULL, sizeof (pthread_mutexattr_t) + sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); |
| 1129 | | if (!uwsgi.sharedareamutex) { |
| 1130 | | perror ("mmap()"); |
| 1131 | | exit (1); |
| 1132 | | } |
| 1133 | | #else |
| 1134 | | fprintf (stderr, "***WARNING*** the sharedarea on OpenBSD is not SMP-safe. Beware of race conditions !!!\n"); |
| 1135 | | #endif |
| 1136 | | uwsgi.sharedarea = mmap (NULL, uwsgi.page_size * uwsgi.sharedareasize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); |
| 1137 | | if (uwsgi.sharedarea) { |
| 1138 | | fprintf (stderr, "shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea); |
| 1139 | | |
| 1140 | | #ifdef __APPLE__ |
| 1141 | | memset (uwsgi.sharedareamutex, 0, sizeof (OSSpinLock)); |
| 1142 | | #else |
| 1143 | | #ifndef __OpenBSD__ |
| 1144 | | if (pthread_mutexattr_init ((pthread_mutexattr_t *) uwsgi.sharedareamutex)) { |
| 1145 | | fprintf (stderr, "unable to allocate mutexattr structure\n"); |
| 1146 | | exit (1); |
| 1147 | | } |
| 1148 | | if (pthread_mutexattr_setpshared ((pthread_mutexattr_t *) uwsgi.sharedareamutex, PTHREAD_PROCESS_SHARED)) { |
| 1149 | | fprintf (stderr, "unable to share mutex\n"); |
| 1150 | | exit (1); |
| 1151 | | } |
| 1152 | | if (pthread_mutex_init ((pthread_mutex_t *) uwsgi.sharedareamutex + sizeof (pthread_mutexattr_t), (pthread_mutexattr_t *) uwsgi.sharedareamutex)) { |
| 1153 | | fprintf (stderr, "unable to initialize mutex\n"); |
| 1154 | | exit (1); |
| 1155 | | } |
| 1156 | | #endif |
| 1157 | | #endif |
| 1158 | | |
| 1159 | | } |
| 1160 | | else { |
| 1161 | | perror ("mmap()"); |
| 1162 | | exit (1); |
| 1163 | | } |
| 1164 | | |
| 1165 | | } |
| 1166 | | |
| 1167 | | init_uwsgi_embedded_module (); |
| 1168 | | #endif |
| 1169 | | #endif |
| 1170 | | |
| 1171 | | |
| 1172 | | |
| 1173 | | #ifdef ROCK_SOLID |
| 1174 | | |
| 1175 | | |
| 1176 | | wi = malloc (sizeof (struct uwsgi_app)); |
| 1177 | | if (wi == NULL) { |
| 1178 | | perror ("malloc()"); |
| 1179 | | exit (1); |
| 1180 | | } |
| 1181 | | memset (wi, 0, sizeof (struct uwsgi_app)); |
| 1182 | | |
| 1183 | | // load wsgi module/script |
| 1184 | | for (i = optind; i < argc; i++) { |
| 1185 | | init_uwsgi_vars (); |
| 1186 | | wi->wsgi_module = PyImport_ImportModule (argv[i]); |
| 1187 | | if (!wi->wsgi_module) { |
| 1188 | | PyErr_Print (); |
| 1189 | | exit (1); |
| 1190 | | } |
| 1191 | | wi->wsgi_dict = PyModule_GetDict (wi->wsgi_module); |
| 1192 | | if (!wi->wsgi_dict) { |
| 1193 | | PyErr_Print (); |
| 1194 | | exit (1); |
| 1195 | | } |
| 1196 | | wi->wsgi_callable = PyDict_GetItemString (wi->wsgi_dict, "application"); |
| 1197 | | if (!wi->wsgi_callable) { |
| 1198 | | PyErr_Print (); |
| 1199 | | exit (1); |
| 1200 | | } |
| 1201 | | wi->wsgi_environ = PyDict_New (); |
| 1202 | | if (!wi->wsgi_environ) { |
| 1203 | | PyErr_Print (); |
| 1204 | | exit (1); |
| 1205 | | } |
| 1206 | | |
| 1207 | | wi->wsgi_harakiri = PyDict_GetItemString (wi->wsgi_dict, "harakiri"); |
| 1208 | | |
| 1209 | | wi->wsgi_args = PyTuple_New (2); |
| 1210 | | if (!wi->wsgi_args) { |
| 1211 | | PyErr_Print (); |
| 1212 | | exit (1); |
| 1213 | | } |
| 1214 | | if (PyTuple_SetItem (wi->wsgi_args, 0, wi->wsgi_environ)) { |
| 1215 | | PyErr_Print (); |
| 1216 | | exit (1); |
| 1217 | | } |
| 1218 | | if (PyTuple_SetItem (wi->wsgi_args, 1, wsgi_spitout)) { |
| 1219 | | PyErr_Print (); |
| 1220 | | exit (1); |
| 1221 | | } |
| 1222 | | break; |
| 1223 | | } |
| 1224 | | |
| 1225 | | if (!wi->wsgi_module) { |
| 1226 | | fprintf (stderr, "unable to find the wsgi script. Have you specified it ?\n"); |
| 1227 | | exit (1); |
| 1228 | | } |
| 1229 | | #endif |
| 1230 | | |
| 1231 | | #ifndef ROCK_SOLID |
| 1232 | | Py_OptimizeFlag = uwsgi.py_optimize; |
| 1233 | | |
| 1234 | | uwsgi.main_thread = PyThreadState_Get (); |
| 1235 | | |
| 1236 | | |
| 1237 | | if (uwsgi.has_threads) { |
| 1238 | | PyEval_InitThreads (); |
| 1239 | | fprintf (stderr, "threads support enabled\n"); |
| 1240 | | } |
| 1241 | | |
| 1242 | | #endif |
| 1243 | | |
| 1244 | | if (!no_server) { |
| 1245 | | #ifndef UNBIT |
| 1246 | | if (socket_name != NULL && !is_a_reload) { |
| 1247 | | #ifdef SCTP |
| 1248 | | if (!strncmp (socket_name, "sctp:", 5)) { |
| 1249 | | char *sctp_port = strchr (socket_name + 5, ':'); |
| 1250 | | if (sctp_port == NULL) { |
| 1251 | | fprintf (stderr, "invalid SCTP port ! syntax: sctp:ip1,ip2,ipN:port\n"); |
| 1252 | | exit (1); |
| 1253 | | } |
| 1254 | | uwsgi.serverfd = bind_to_sctp (socket_name + 5, uwsgi.listen_queue, sctp_port); |
| 1255 | | i_am_sctp = 1; |
| 1256 | | } |
| 1257 | | else { |
| 1258 | | #endif |
| 1259 | | char *tcp_port = strchr (socket_name, ':'); |
| 1260 | | if (tcp_port == NULL) { |
| 1261 | | uwsgi.serverfd = bind_to_unix (socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); |
| 1262 | | } |
| 1263 | | else { |
| 1264 | | uwsgi.serverfd = bind_to_tcp (socket_name, uwsgi.listen_queue, tcp_port); |
| 1265 | | } |
| 1266 | | |
| 1267 | | if (uwsgi.serverfd < 0) { |
| 1268 | | fprintf (stderr, "unable to create the server socket.\n"); |
| 1269 | | exit (1); |
| 1270 | | } |
| 1271 | | #ifdef SCTP |
| 1272 | | } |
| 1273 | | #endif |
| 1274 | | } |
| 1275 | | #endif |
| 1276 | | |
| 1277 | | socket_type_len = sizeof (int); |
| 1278 | | if (getsockopt (uwsgi.serverfd, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) { |
| 1279 | | perror ("getsockopt()"); |
| 1280 | | fprintf(stderr, "The -s/--socket option is missing and stdin is not a socket.\n"); |
| 1281 | | exit (1); |
| 1282 | | } |
| 1283 | | |
| 1284 | | } |
| 1285 | | |
| 1286 | | |
| 1287 | | |
| 1288 | | #ifndef ROCK_SOLID |
| 1289 | | if (uwsgi.single_interpreter == 1) { |
| 1290 | | init_uwsgi_vars (); |
| 1291 | | } |
| 1292 | | |
| 1293 | | memset (uwsgi.wsgi_apps, 0, sizeof (uwsgi.wsgi_apps)); |
| 1294 | | |
| 1295 | | |
| 1296 | | #endif |
| 1297 | | |
| 1298 | | |
| 1299 | | |
| 1300 | | uwsgi.poll.events = POLLIN; |
| 1301 | | |
| 1302 | | memset (&wsgi_req, 0, sizeof (struct wsgi_request)); |
| 1303 | | |
| 1304 | | /* shared area for workers */ |
| 1305 | | uwsgi.workers = (struct uwsgi_worker *) mmap (NULL, sizeof (struct uwsgi_worker) * uwsgi.maxworkers + 1, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); |
| 1306 | | if (!uwsgi.workers) { |
| 1307 | | perror ("mmap()"); |
| 1308 | | exit (1); |
| 1309 | | } |
| 1310 | | memset (uwsgi.workers, 0, sizeof (struct uwsgi_worker) * uwsgi.maxworkers + 1); |
| 1311 | | |
| 1312 | | uwsgi.mypid = getpid (); |
| 1313 | | masterpid = uwsgi.mypid; |
| 1314 | | |
| 1315 | | #ifndef ROCK_SOLID |
| 1316 | | #ifndef UNBIT |
| 1317 | | if (uwsgi.pidfile) { |
| 1318 | | fprintf (stderr, "writing pidfile to %s\n", uwsgi.pidfile); |
| 1319 | | pidfile = fopen (uwsgi.pidfile, "w"); |
| 1320 | | if (!pidfile) { |
| 1321 | | perror ("fopen"); |
| 1322 | | exit (1); |
| 1323 | | } |
| 1324 | | if (fprintf (pidfile, "%d\n", masterpid) < 0) { |
| 1325 | | fprintf (stderr, "could not write pidfile.\n"); |
| 1326 | | } |
| 1327 | | fclose (pidfile); |
| 1328 | | } |
| 1329 | | #endif |
| 1330 | | #endif |
| 1331 | | |
| 1332 | | if (uwsgi.buffer_size > 65536) { |
| 1333 | | fprintf (stderr, "invalid buffer size.\n"); |
| 1334 | | exit (1); |
| 1335 | | } |
| 1336 | | buffer = malloc (uwsgi.buffer_size); |
| 1337 | | if (buffer == NULL) { |
| 1338 | | fprintf (stderr, "unable to allocate memory for buffer.\n"); |
| 1339 | | exit (1); |
| 1340 | | } |
| 1341 | | |
| 1342 | | fprintf (stderr, "request/response buffer (%d bytes) allocated.\n", uwsgi.buffer_size); |
| 1343 | | |
| 1344 | | /* save the masterpid */ |
| 1345 | | uwsgi.workers[0].pid = masterpid; |
| 1346 | | |
| 1347 | | uwsgi.workers[0].current_workers = uwsgi.numproc; |
| 1348 | | |
| 1349 | | fprintf(stderr,"initializing hooks..."); |
| 1350 | | |
| 1351 | | uwsgi.hooks[0] = uwsgi_request_wsgi ; |
| 1352 | | uwsgi.after_hooks[0] = uwsgi_after_request_wsgi ; |
| 1353 | | |
| 1354 | | uwsgi.hooks[UWSGI_MODIFIER_ADMIN_REQUEST] = uwsgi_request_admin ; //10 |
| 1355 | | uwsgi.hooks[UWSGI_MODIFIER_SPOOL_REQUEST] = uwsgi_request_spooler ; //17 |
| 1356 | | uwsgi.hooks[UWSGI_MODIFIER_FASTFUNC] = uwsgi_request_fastfunc ; //26 |
| 1357 | | |
| 1358 | | uwsgi.hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_request_wsgi ; // 30 |
| 1359 | | uwsgi.after_hooks[UWSGI_MODIFIER_MANAGE_PATH_INFO] = uwsgi_after_request_wsgi; // 30 |
| 1360 | | |
| 1361 | | uwsgi.hooks[UWSGI_MODIFIER_MESSAGE_MARSHAL] = uwsgi_request_marshal ; //33 |
| 1362 | | uwsgi.hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping ; //100 |
| 1363 | | |
| 1364 | | fprintf(stderr,"done.\n"); |
| 1365 | | |
| 1366 | | |
| 1367 | | #ifndef ROCK_SOLID |
| 1368 | | if (uwsgi.wsgi_config != NULL) { |
| 1369 | | uwsgi_wsgi_config (); |
| 1370 | | } |
| 1371 | | #endif |
| 1372 | | |
| 1373 | | #ifndef UNBIT |
| 1374 | | #ifndef ROCK_SOLID |
| 1375 | | else if (uwsgi.xml_config != NULL) { |
| 1376 | | uwsgi_xml_config (); |
| 1377 | | } |
| 1378 | | #endif |
| 1379 | | #endif |
| 1380 | | |
| 1381 | | #ifndef ROCK_SOLID |
| 1382 | | else if (uwsgi.paste != NULL) { |
| 1383 | | uwsgi_paste_config (); |
| 1384 | | } |
| 1385 | | #endif |
| 1386 | | |
| 1387 | | if (uwsgi.test_module != NULL) { |
| 1388 | | if (PyImport_ImportModule (uwsgi.test_module)) { |
| 1389 | | exit (0); |
| 1390 | | } |
| 1391 | | exit (1); |
| 1392 | | } |
| 1393 | | |
| 1394 | | |
| 1395 | | |
| 1396 | | #ifndef UNBIT |
| 1397 | | #ifndef ROCK_SOLID |
| 1398 | | if (no_server) { |
| 1399 | | fprintf (stderr, "no-server mode requested. Goodbye.\n"); |
| 1400 | | exit (0); |
| 1401 | | } |
| 1402 | | #endif |
| 1403 | | #endif |
| 1404 | | |
| 1405 | | /* preforking() */ |
| 1406 | | if (uwsgi.master_process) { |
| 1407 | | if (is_a_reload) { |
| 1408 | | fprintf (stderr, "gracefully (RE)spawned uWSGI master process (pid: %d)\n", uwsgi.mypid); |
| 1409 | | } |
| 1410 | | else { |
| 1411 | | fprintf (stderr, "spawned uWSGI master process (pid: %d)\n", uwsgi.mypid); |
| 1412 | | } |
| 1413 | | } |
| 1414 | | |
| 1415 | | #ifdef UNBIT |
| 1416 | | if (single_app_mode == 1) { |
| 1417 | | wsgi_req.wsgi_script = getenv ("UWSGI_SCRIPT"); |
| 1418 | | if (wsgi_req.wsgi_script) { |
| 1419 | | wsgi_req.wsgi_script_len = strlen (wsgi_req.wsgi_script); |
| 1420 | | } |
| 1421 | | else { |
| 1422 | | fprintf (stderr, "UWSGI_SCRIPT env var not set !\n"); |
| 1423 | | exit (1); |
| 1424 | | } |
| 1425 | | |
| 1426 | | init_uwsgi_app (NULL, NULL); |
| 1427 | | } |
| 1428 | | #endif |
| 1429 | | |
| 1430 | | #ifndef ROCK_SOLID |
| 1431 | | #ifndef PYTHREE |
| 1432 | | if (spool_dir != NULL) { |
| 1433 | | uwsgi.workers[0].spooler_pid = spooler_start (uwsgi.serverfd, uwsgi_module); |
| 1434 | | } |
| 1435 | | #endif |
| 1436 | | #endif |
| 1437 | | |
| 1438 | | |
| 1439 | | if (!uwsgi.master_process) { |
| 1440 | | if (uwsgi.numproc == 1) { |
| 1441 | | fprintf (stderr, "spawned uWSGI worker 1 (and the only) (pid: %d)\n", masterpid); |
| 1442 | | } |
| 1443 | | else { |
| 1444 | | fprintf (stderr, "spawned uWSGI worker 1 (pid: %d)\n", masterpid); |
| 1445 | | } |
| 1446 | | uwsgi.workers[1].pid = masterpid; |
| 1447 | | uwsgi.workers[1].id = 1; |
| 1448 | | uwsgi.workers[1].last_spawn = time (NULL); |
| 1449 | | uwsgi.workers[1].manage_next_request = 1; |
| 1450 | | uwsgi.mywid = 1; |
| 1451 | | gettimeofday (&last_respawn, NULL); |
| 1452 | | respawn_delta = last_respawn.tv_sec; |
| 1453 | | } |
| 1454 | | |
| 1455 | | |
| 1456 | | for (i = 2-uwsgi.master_process ; i < uwsgi.numproc + 1; i++) { |
| 1457 | | /* let the worker know his worker_id (wid) */ |
| 1458 | | pid = fork (); |
| 1459 | | if (pid == 0) { |
| 1460 | | uwsgi.mypid = getpid (); |
| 1461 | | uwsgi.workers[i].pid = uwsgi.mypid; |
| 1462 | | uwsgi.workers[i].id = i; |
| 1463 | | uwsgi.workers[i].last_spawn = time (NULL); |
| 1464 | | uwsgi.workers[i].manage_next_request = 1; |
| 1465 | | uwsgi.mywid = i; |
| 1466 | | if (uwsgi.serverfd != 0 && uwsgi.master_process == 1) { |
| 1467 | | /* close STDIN for workers */ |
| 1468 | | close (0); |
| 1469 | | } |
| 1470 | | break; |
| 1471 | | } |
| 1472 | | else if (pid < 1) { |
| 1473 | | perror ("fork()"); |
| 1474 | | exit (1); |
| 1475 | | } |
| 1476 | | else { |
| 1477 | | fprintf (stderr, "spawned uWSGI worker %d (pid: %d)\n", i, pid); |
| 1478 | | gettimeofday (&last_respawn, NULL); |
| 1479 | | respawn_delta = last_respawn.tv_sec; |
| 1480 | | } |
| 1481 | | } |
| 1482 | | |
| 1483 | | |
| 1484 | | if (getpid () == masterpid && uwsgi.master_process == 1) { |
| 1485 | | /* route signals to workers... */ |
| 1486 | | signal (SIGHUP, (void *) &grace_them_all); |
| 1487 | | signal (SIGTERM, (void *) &reap_them_all); |
| 1488 | | signal (SIGINT, (void *) &kill_them_all); |
| 1489 | | signal (SIGQUIT, (void *) &kill_them_all); |
| 1490 | | /* used only to avoid human-errors */ |
| 1491 | | #ifndef ROCK_SOLID |
| 1492 | | #ifndef UNBIT |
| 1493 | | signal (SIGUSR1, (void *) &stats); |
| 1494 | | #endif |
| 1495 | | #endif |
| 1496 | | |
| 1497 | | if (udp_socket) { |
| 1498 | | udp_poll.fd = bind_to_udp (udp_socket); |
| 1499 | | if (udp_poll.fd < 0) { |
| 1500 | | fprintf (stderr, "unable to bind to udp socket. SNMP and cluster management services will be disabled.\n"); |
| 1501 | | } |
| 1502 | | else { |
| 1503 | | fprintf (stderr, "UDP server enabled.\n"); |
| 1504 | | udp_poll.events = POLLIN; |
| 1505 | | } |
| 1506 | | } |
| 1507 | | for (;;) { |
| 1508 | | if (ready_to_die >= uwsgi.numproc && uwsgi.to_hell) { |
| 1509 | | #ifndef ROCK_SOLID |
| 1510 | | if (spool_dir && uwsgi.workers[0].spooler_pid > 0) { |
| 1511 | | kill (uwsgi.workers[0].spooler_pid, SIGKILL); |
| 1512 | | } |
| 1513 | | |
| 1514 | | #endif |
| 1515 | | fprintf (stderr, "goodbye to uWSGI.\n"); |
| 1516 | | exit (0); |
| 1517 | | } |
| 1518 | | if (ready_to_reload >= uwsgi.numproc && uwsgi.to_heaven) { |
| 1519 | | #ifndef ROCK_SOLID |
| 1520 | | if (spool_dir && uwsgi.workers[0].spooler_pid > 0) { |
| 1521 | | kill (uwsgi.workers[0].spooler_pid, SIGKILL); |
| 1522 | | } |
| 1523 | | #endif |
| 1524 | | fprintf (stderr, "binary reloading uWSGI...\n"); |
| 1525 | | if (chdir (cwd)) { |
| 1526 | | perror ("chdir()"); |
| 1527 | | exit (1); |
| 1528 | | } |
| 1529 | | /* check fd table (a module can obviosly open some fd on initialization...) */ |
| 1530 | | fprintf (stderr, "closing all fds > 2 (_SC_OPEN_MAX = %ld)...\n", sysconf (_SC_OPEN_MAX)); |
| 1531 | | for (i = 3; i < sysconf (_SC_OPEN_MAX); i++) { |
| 1532 | | if (i == uwsgi.serverfd) { |
| 1533 | | continue; |
| 1534 | | } |
| 1535 | | close (i); |
| 1536 | | } |
| 1537 | | if (uwsgi.serverfd != 3) { |
| 1538 | | if (dup2 (uwsgi.serverfd, 3) < 0) { |
| 1539 | | perror ("dup2()"); |
| 1540 | | exit (1); |
| 1541 | | } |
| 1542 | | } |
| 1543 | | fprintf (stderr, "running %s\n", binary_path); |
| 1544 | | strcpy (argv[0], binary_path); |
| 1545 | | execve (binary_path, argv, environ); |
| 1546 | | perror ("execve()"); |
| 1547 | | exit (1); |
| 1548 | | } |
| 1549 | | diedpid = waitpid (WAIT_ANY, &waitpid_status, WNOHANG); |
| 1550 | | if (diedpid == -1) { |
| 1551 | | perror ("waitpid()"); |
| 1552 | | /* here is better to reload all the uWSGI stack */ |
| 1553 | | fprintf (stderr, "something horrible happened...\n"); |
| 1554 | | reap_them_all (); |
| 1555 | | exit (1); |
| 1556 | | } |
| 1557 | | else if (diedpid == 0) { |
| 1558 | | /* PLEASE, do not run python threads in the master process, you can potentially destroy the world, |
| 1559 | | we support this for hyperultramegagodprogrammer and systems |
| 1560 | | */ |
| 1561 | | #ifndef ROCK_SOLID |
| 1562 | | if (uwsgi.has_threads && uwsgi.options[UWSGI_OPTION_THREADS] == 1) { |
| 1563 | | uwsgi._save = PyEval_SaveThread (); |
| 1564 | | uwsgi.i_have_gil = 0; |
| 1565 | | } |
| 1566 | | #endif |
| 1567 | | /* all processes ok, doing status scan after N seconds */ |
| 1568 | | check_interval.tv_sec = uwsgi.options[UWSGI_OPTION_MASTER_INTERVAL]; |
| 1569 | | if (!check_interval.tv_sec) |
| 1570 | | check_interval.tv_sec = 1; |
| 1571 | | |
| 1572 | | if (udp_socket && udp_poll.fd >= 0) { |
| 1573 | | rlen = poll (&udp_poll, 1, check_interval.tv_sec * 1000); |
| 1574 | | if (rlen < 0) { |
| 1575 | | perror ("poll()"); |
| 1576 | | } |
| 1577 | | else if (rlen > 0) { |
| 1578 | | udp_len = sizeof (udp_client); |
| 1579 | | rlen = recvfrom (udp_poll.fd, buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len); |
| 1580 | | if (rlen < 0) { |
| 1581 | | perror ("recvfrom()"); |
| 1582 | | } |
| 1583 | | else if (rlen > 0) { |
| 1584 | | memset (udp_client_addr, 0, 16); |
| 1585 | | if (inet_ntop (AF_INET, &udp_client, udp_client_addr, 16)) { |
| 1586 | | fprintf (stderr, "received udp packet of %d bytes from %s:%d\n", rlen, udp_client_addr, ntohs (udp_client.sin_port)); |
| 1587 | | if (buffer[0] == 0x30) { |
| 1588 | | manage_snmp (udp_poll.fd, (uint8_t *) buffer, rlen, &udp_client); |
| 1589 | | } |
| 1590 | | } |
| 1591 | | else { |
| 1592 | | perror ("inet_ntop()"); |
| 1593 | | } |
| 1594 | | } |
| 1595 | | } |
| 1596 | | } |
| 1597 | | else { |
| 1598 | | select (0, NULL, NULL, NULL, &check_interval); |
| 1599 | | } |
| 1600 | | working_workers = 0; |
| 1601 | | blocking_workers = 0; |
| 1602 | | #ifndef ROCK_SOLID |
| 1603 | | if (uwsgi.has_threads && !uwsgi.i_have_gil) { |
| 1604 | | PyEval_RestoreThread (uwsgi._save); |
| 1605 | | uwsgi.i_have_gil = 1; |
| 1606 | | } |
| 1607 | | #endif |
| 1608 | | check_interval.tv_sec = uwsgi.options[UWSGI_OPTION_MASTER_INTERVAL]; |
| 1609 | | if (!check_interval.tv_sec) |
| 1610 | | check_interval.tv_sec = 1; |
| 1611 | | for (i = 1; i <= uwsgi.workers[0].current_workers; i++) { |
| 1612 | | /* first check for harakiri */ |
| 1613 | | if (uwsgi.workers[i].harakiri > 0) { |
| 1614 | | if (uwsgi.workers[i].harakiri < time (NULL)) { |
| 1615 | | /* first try to invoke the harakiri() custom handler */ |
| 1616 | | /* TODO */ |
| 1617 | | /* then brutally kill the worker */ |
| 1618 | | kill (uwsgi.workers[i].pid, SIGKILL); |
| 1619 | | } |
| 1620 | | } |
| 1621 | | /* load counters */ |
| 1622 | | if (uwsgi.workers[i].in_request) |
| 1623 | | working_workers++; |
| 1624 | | |
| 1625 | | if (uwsgi.workers[i].blocking) |
| 1626 | | blocking_workers++; |
| 1627 | | |
| 1628 | | uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time; |
| 1629 | | } |
| 1630 | | |
| 1631 | | /* check if i need to add a subworker */ |
| 1632 | | //fprintf(stderr,"working workers: %d\n", working_workers); |
| 1633 | | if (working_workers >= uwsgi.workers[0].current_workers) { |
| 1634 | | /* ok the system is overloaded, check if some worker is in blocking mode */ |
| 1635 | | if (blocking_workers > 0) { |
| 1636 | | /* check if is it safe to add a new worker (for now check only for enough free memory) */ |
| 1637 | | fprintf (stderr, "adding a new subworker as there are workers in blocking mode...\n"); |
| 1638 | | uwsgi.mywid = uwsgi.workers[0].current_workers + 1; |
| 1639 | | pid = fork (); |
| 1640 | | if (pid < 0) { |
| 1641 | | perror ("fork()"); |
| 1642 | | } |
| 1643 | | else if (pid > 0) { |
| 1644 | | fprintf (stderr, "spawned uWSGI subworker (pid: %d)\n", pid); |
| 1645 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].id = uwsgi.workers[0].current_workers + 1; |
| 1646 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].pid = pid; |
| 1647 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].harakiri = 0; |
| 1648 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].requests = 0; |
| 1649 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].failed_requests = 0; |
| 1650 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].respawn_count++; |
| 1651 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].last_spawn = time (NULL); |
| 1652 | | uwsgi.workers[uwsgi.workers[0].current_workers + 1].manage_next_request = 1; |
| 1653 | | uwsgi.workers[0].current_workers++; |
| 1654 | | } |
| 1655 | | else if (pid == 0) { |
| 1656 | | uwsgi.mypid = getpid (); |
| 1657 | | break; |
| 1658 | | } |
| 1659 | | } |
| 1660 | | } |
| 1661 | | else { |
| 1662 | | /* the system is no more overloaded, mark subworkers */ |
| 1663 | | for (i = uwsgi.numproc + 1; i <= uwsgi.workers[0].current_workers; i++) { |
| 1664 | | uwsgi.workers[i].manage_next_request = 0; |
| 1665 | | } |
| 1666 | | } |
| 1667 | | |
| 1668 | | /* now check for subworkers to remove */ |
| 1669 | | for (i = uwsgi.workers[0].current_workers; i > uwsgi.numproc; i--) { |
| 1670 | | if (uwsgi.workers[i].manage_next_request) |
| 1671 | | break; |
| 1672 | | /* reset this worker (no interest in killing it) */ |
| 1673 | | memset (&uwsgi.workers[i], 0, sizeof (struct uwsgi_worker)); |
| 1674 | | uwsgi.workers[0].current_workers--; |
| 1675 | | } |
| 1676 | | continue; |
| 1677 | | } |
| 1678 | | #ifndef ROCK_SOLID |
| 1679 | | #ifndef PYTHREE |
| 1680 | | /* reload the spooler */ |
| 1681 | | if (spool_dir && uwsgi.workers[0].spooler_pid > 0) { |
| 1682 | | if (diedpid == uwsgi.workers[0].spooler_pid) { |
| 1683 | | fprintf(stderr,"OOOPS the spooler is no more...trying respawn...\n"); |
| 1684 | | uwsgi.workers[0].spooler_pid = spooler_start (uwsgi.serverfd, uwsgi_module); |
| 1685 | | continue; |
| 1686 | | } |
| 1687 | | } |
| 1688 | | #endif |
| 1689 | | #endif |
| 1690 | | /* check for reloading */ |
| 1691 | | if (WIFEXITED (waitpid_status)) { |
| 1692 | | if (WEXITSTATUS (waitpid_status) == UWSGI_RELOAD_CODE && uwsgi.to_heaven) { |
| 1693 | | ready_to_reload++; |
| 1694 | | continue; |
| 1695 | | } |
| 1696 | | else if (WEXITSTATUS (waitpid_status) == UWSGI_END_CODE && uwsgi.to_hell) { |
| 1697 | | ready_to_die++; |
| 1698 | | continue; |
| 1699 | | } |
| 1700 | | } |
| 1701 | | |
| 1702 | | /* subworkers need to be respawned ? i do not think so */ |
| 1703 | | if (find_worker_id (diedpid) > uwsgi.numproc) { |
| 1704 | | fprintf (stderr, "OOPS ! process %d (subworker id %d) died :( i will not respawn it.\n", diedpid, find_worker_id (diedpid)); |
| 1705 | | /* decrease the number of workers */ |
| 1706 | | if (uwsgi.workers[0].current_workers > uwsgi.numproc) { |
| 1707 | | uwsgi.workers[find_worker_id (diedpid)].manage_next_request = 0; |
| 1708 | | } |
| 1709 | | continue; |
| 1710 | | } |
| 1711 | | fprintf (stderr, "DAMN ! process %d died :( trying respawn ...\n", diedpid); |
| 1712 | | gettimeofday (&last_respawn, NULL); |
| 1713 | | if (last_respawn.tv_sec == respawn_delta) { |
| 1714 | | fprintf (stderr, "worker respawning too fast !!! i have to sleep a bit...\n"); |
| 1715 | | /* TODO, user configurable fork throttler */ |
| 1716 | | sleep (2); |
| 1717 | | } |
| 1718 | | gettimeofday (&last_respawn, NULL); |
| 1719 | | respawn_delta = last_respawn.tv_sec; |
| 1720 | | uwsgi.mywid = find_worker_id (diedpid); |
| 1721 | | pid = fork (); |
| 1722 | | if (pid == 0) { |
| 1723 | | uwsgi.mypid = getpid (); |