Start a debugging session before calling EVAL implementation. * The technique we use is to capture the client socket file descriptor, * in order to perform direct I/O with it from within Lua hooks. This * way we don't have to re-enter Redis in order to handle I/O. * * The function returns 1 if the caller should proceed to call EVAL, * and 0 if instead the caller should abort the operation (t
| 1939 | * The caller should call ldbEndSession() only if ldbStartSession() |
| 1940 | * returned 1. */ |
| 1941 | int ldbStartSession(client *c) { |
| 1942 | ldb.forked = (c->flags & CLIENT_LUA_DEBUG_SYNC) == 0; |
| 1943 | if (ldb.forked) { |
| 1944 | pid_t cp = redisFork(CHILD_TYPE_LDB); |
| 1945 | if (cp == -1) { |
| 1946 | addReplyError(c,"Fork() failed: can't run EVAL in debugging mode."); |
| 1947 | return 0; |
| 1948 | } else if (cp == 0) { |
| 1949 | /* Child. Let's ignore important signals handled by the parent. */ |
| 1950 | struct sigaction act; |
| 1951 | sigemptyset(&act.sa_mask); |
| 1952 | act.sa_flags = 0; |
| 1953 | act.sa_handler = SIG_IGN; |
| 1954 | sigaction(SIGTERM, &act, NULL); |
| 1955 | sigaction(SIGINT, &act, NULL); |
| 1956 | |
| 1957 | /* Log the creation of the child and close the listening |
| 1958 | * socket to make sure if the parent crashes a reset is sent |
| 1959 | * to the clients. */ |
| 1960 | serverLog(LL_WARNING,"Redis forked for debugging eval"); |
| 1961 | redisSetCpuAffinity(server.bgsave_cpulist); |
| 1962 | } else { |
| 1963 | /* Parent */ |
| 1964 | listAddNodeTail(ldb.children,(void*)(unsigned long)cp); |
| 1965 | freeClientAsync(c); /* Close the client in the parent side. */ |
| 1966 | return 0; |
| 1967 | } |
| 1968 | } else { |
| 1969 | serverLog(LL_WARNING, |
| 1970 | "Redis synchronous debugging eval session started"); |
| 1971 | } |
| 1972 | |
| 1973 | /* Setup our debugging session. */ |
| 1974 | connBlock(ldb.conn); |
| 1975 | connSendTimeout(ldb.conn,5000); |
| 1976 | ldb.active = 1; |
| 1977 | |
| 1978 | /* First argument of EVAL is the script itself. We split it into different |
| 1979 | * lines since this is the way the debugger accesses the source code. */ |
| 1980 | sds srcstring = sdsdup(c->argv[1]->ptr); |
| 1981 | size_t srclen = sdslen(srcstring); |
| 1982 | while(srclen && (srcstring[srclen-1] == '\n' || |
| 1983 | srcstring[srclen-1] == '\r')) |
| 1984 | { |
| 1985 | srcstring[--srclen] = '\0'; |
| 1986 | } |
| 1987 | sdssetlen(srcstring,srclen); |
| 1988 | ldb.src = sdssplitlen(srcstring,sdslen(srcstring),"\n",1,&ldb.lines); |
| 1989 | sdsfree(srcstring); |
| 1990 | return 1; |
| 1991 | } |
| 1992 | |
| 1993 | /* End a debugging session after the EVAL call with debugging enabled |
| 1994 | * returned. */ |
no test coverage detected